Website-Suche

typescript - Wie erhält man den Rückgabetyp für bestimmte Parameter einer generischen Funktion?


Ich möchte einen Hilfstyp erstellen, der eine Signatur einer generischen Funktion und deren Argumente übernimmt. Er sollte in den Rückgabewerttyp der Signatur resultieren, als ob sie mit den bereitgestellten Argumenten ausgeführt würde.

Ich habe dies versucht:

type GetReturnType<T extends (...args: any) => any, B> = T extends (...args: any) => infer R ? R : never;

Aber alle Generika enden entweder als unknown oder never.

Einige Beispiel-Funktionen, die ich vielleicht übergeben möchte:

function myFn1<T>(x: T) {
    return {
        a: x,
    }
}

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

function myFn3<T>(x: T) {
    if (typeof x == "string") {
        return "yes" as (T extends string ? "yes" : "no");
    } else {
        return "no" as (T extends string ? "yes" : "no");
    }
}

Und wie ich GetReturnType gerne verwendet sehen würde:

type Return1 = GetReturnType<typeof myFn1, [x: number]>; // expected {a: number}
type Return2 = GetReturnType<typeof myFn2, [x: number]>; // expected number[]
type Return3A = GetReturnType<typeof myFn3, [x: number]>; // expected "no"
type Return3B = GetReturnType<typeof myFn3, [x: string]>; // expected "yes"

Spielplatzlink

TypeScript hat bereits ein System, um die generischen Typen von Funktionen abzuleiten. Zum Beispiel wird myFn3("some string") das erste generische Argument als string ableiten und dadurch wird der zurückgegebene Wert "yes" sein. Ich möchte dieses System nutzen, um den Rückgabewert zu erhalten. Andere Fragen auf SO fragen, wie man dies macht, wenn die Generics bekannt sind, aber ich möchte wissen, wie man dies macht, wenn die Generics abgeleitet werden.

Antwort #1

const to = <A>(value: A) => ({ value } as const);

type ApplyTo<A> = ReturnType<typeof to<A>>;

const map = <A extends unknown[]>(value: readonly [...A]) => value.map(to) as {
  [K in keyof A]: ApplyTo<A[K]>;
};


type t2 = ReturnType<typeof map<["a", "b", "c"]>>;
// type t2 = [{
//   readonly value: "a";
// }, {
//   readonly value: "b";
// }, {
//   readonly value: "c";
// }]

Ich denke, das ist so nah dran, wie es geht. Es wäre besser, wenn wir to als Parameter übergeben könnten, aber soweit ich weiß, ist das nicht möglich.

Antwort #2

Die gleiche Frage, warum ich einen zusätzlichen Wert zurückgeben kann

type RX = { id: number; name: string };
type GetProduct = (name: string) => RX;

const getProduct: GetProduct = (name) => ({ id: 123, name, city: "" });

wie Stadt hier