I have exported a function from some module that looks like:
export function MyFunc() {
return {
foo: (in: A) => void
}
}
Titian's solution above works great if the Generic is only applied inside the function body.
However, there are cases that the Generic Type is a part of the arguments and/or return type. e.g.
function MyFunc3(r: number, p: T, x: boolean): T {
return p;
}
So, to generalize Titian's solution and support fixating both the arguments and the return type of any generic function, I wrote the following:
// From https://stackoverflow.com/a/53808212 by jcalz (https://stackoverflow.com/users/2887218)
export type IfEquals =
(() => G extends T ? 1 : 2) extends
(() => G extends U ? 1 : 2) ? Y : N;
// Aidin: Please comment if you could make the following shorter!
type ReplaceType = IfEquals;
type ReplaceTypeInArray =
ARR extends [] ? []
: ARR extends [infer P0] ? [P0 extends F ? T : P0]
: ARR extends [infer P0, infer P1] ? [ReplaceType, ReplaceType]
: ARR extends [infer P0, infer P1, infer P2] ? [ReplaceType, ReplaceType, ReplaceType]
: ARR extends [infer P0, infer P1, infer P2, infer P3] ? [ReplaceType, ReplaceType, ReplaceType, ReplaceType]
: ARR extends [infer P0, infer P1, infer P2, infer P3, infer P4] ? [ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType]
: ARR extends [infer P0, infer P1, infer P2, infer P3, infer P4, infer P5] ? [ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType]
: ARR extends [infer P0, infer P1, infer P2, infer P3, infer P4, infer P5, infer P6] ? [ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType]
: ARR extends [infer P0, infer P1, infer P2, infer P3, infer P4, infer P5, infer P6, infer P7] ? [ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType]
: ARR extends [infer P0, infer P1, infer P2, infer P3, infer P4, infer P5, infer P6, infer P7, infer P8] ? [ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType, ReplaceType]
: never;
type ALL = string | number | object | boolean;
export function MyFunc1() {
return {
foo: (os : T) => {}
}
}
function MyFunc2(r: 55, p: T, x: boolean): T {
return p;
}
// Inspired by https://stackoverflow.com/a/52964723 by Titian (https://stackoverflow.com/users/125734)
class Helper1 {
Fixate = (...args: ReplaceTypeInArray, ALL, T>) => MyFunc1(...args);
}
type FixatedFunc1 = Helper1['Fixate'];
// -- Usage
type ForNumber1 = FixatedFunc1 // {foo: (os: number) => void;}
type ForString1 = FixatedFunc1 // {foo: (os: string) => void;}
// ~~~~~~~~~~~~~~~~~~~
class Helper2 {
Fixate = (...args: ReplaceTypeInArray, ALL, T>) => MyFunc2(...args);
}
type FixatedFunc2 = Helper2['Fixate'];
// -- Usage
type ForNumber2 = FixatedFunc2 // (args_0: 55, args_1: number, args_2: boolean) => number
type ForString2 = FixatedFunc2 // (args_0: 55, args_1: string, args_2: boolean) => string
Playground Link (Contains all 3 parts)
Now, one can simply use ReturnType or Parameteres on any of these fixated function types!