javascript - TypeScript - ReturnType av en generisk funktion fungerar inte


Det finns en funktion i TypeScript som heter ReturnType<TFunction> som låter dig härleda returtypen för en viss funktion, så här

function arrayOf(item: string): string[] {
  return [item]
}

Jag har dock problem med att använda det med generiska funktioner:

function arrayOf<T>(item: T): T[] {
  return [item]
}

type R = ReturnType<typeof arrayOf> // R = {}[]
type R = ReturnType<typeof arrayOf<number>> // syntax error
// etc.

Genom att använda det bästa svaret från Typescript ReturnType av en generisk funktion har jag försökt detta: (förresten, detta är inte en duplicering, det är annorlunda eftersom lösningen och frågan gäller detta fall)

function arrayOf<T>(x: T): T[] {
  return [x];
}

type GenericReturnType<R, X> = X extends (...args: any[]) => R ? R : never;

type N = GenericReturnType<number, <T>(item: T) => T[]>; // N = never

Jag har också försökt följande:

type GenericReturnType<TGenericParameter, TFunction> = TFunction extends (...args: any[]) => infer R ? R : never;

type N = GenericReturnType<number, <T>(item: T) => T[]>; // N = {}[]

såväl som

type GenericReturnType<TGenericParameter, TFunction> = TFunction extends <T>(...args: any[]) => infer R ? R : never;

type N = GenericReturnType<number, <T>(item: T) => T[]>; // N = {}[]

och

type GenericReturnType<TGenericParameter, TFunction> = TFunction extends <T extends TGenericParameter>(...args: any[]) => infer R ? R : never;

type N = GenericReturnType<number, <T>(item: T) => T[]>; // N = {}[]

och också detta

type GenericReturnType<TGenericParameter, TFunction> = TFunction extends (arg: TGenericParameter) => infer R ? R : never;

type N = GenericReturnType<number, <T>(item: T) => T[]>; // N = {}[]

och detta

type GenericReturnType<TGenericParameter, TFunction> = TFunction extends <U extends TGenericParameter>(arg: U) => infer R ? R : never;

type N = GenericReturnType<number, <T>(item: T) => T[]>; // N = {}[]

såväl som

type x = (<T>(item: T) => T[]) extends <T>(arg: T) => infer R ? R : never // x = {}[]

och slutligen

type x = (<T>(item: T) => T[]) extends (arg: number) => infer R ? R : never // x = {}[]

Men ingen av dem ger den mycket önskade typen av number[]

Så, min fråga är, finns det något sätt att skapa något liknande den inbyggda ReturnType som fungerar för funktioner med generiska parametrar, givet typerna för de generiska parametrarna? (alltså en lösning på ovanstående problem)

Svar #1

Jag har samma problem som du och efter otaliga tillfälliga lösningar som inte fungerade, hittade jag en något av en "hack". Detta kanske dock inte är bekvämt i alla fall:

På liknande sätt som svaret som ges av Matt, är poängen att ha en dummyfunktion, men utan att skriva om den. Istället för att skriva en dummyomskrivning av din funktion, skriv en dummyfunktion som returnerar en dummyanvändning av din funktion. Sedan, få den resulterande typen med ReturnType:

function arrayOf<T>(item: T): T[] {
    return [item];
}

const arrayOfNumber = () => arrayOf<number>(1);
type N = ReturnType<typeof arrayOfNumber>;

Från och med TS 3.7, om jag inte har gjort min forskning rätt, är det fortfarande inte möjligt att uppnå de önskade resultaten utan att hitta en lösning. Förhoppningsvis kan vi få något som ser ut så här:

function arrayOf<T>(item: T): T[] {
    return [item];
}

type N = GenericReturnType<typeof arrayOf>; // N<T>

Svar #2

Med tanke på typargumenten till funktionen, inte för närvarande, om du följer länkkedjan till Att få returtypen för en funktion som använder generics. Med tanke på argumenttyperna kan du skriva en icke-generisk dummyfunktion som skickar argument av dessa typer och sedan kontrollera dess returtyp:

function dummy(n: number) { return arrayOf(n); }
type N = ReturnType<typeof dummy>;

Relaterade artiklar