typescript - Hur implementerar man en utility-typ som omvandlar returtypen för vilken funktionstyp som helst till ett löfte?
Jag ville skriva en nyttotyp som kan omvandla vilken funktionstyp som helst (inklusive generiska funktioner) så att den har en Promise som returtyp.
Min idé var denna:
type Promisify<T extends (...args: any) => any> = T extends (...args: infer A) => infer R
? (...args: A) => Promise<R>
: never;
Tyvärr skulle detta inte fungera för generiska typer:
type Bar<T> = () => T extends string ? number: string
// ERROR: Generic type 'Bar' requires 1 type argument(s).
type PromisifyBar = Promisify<Bar>
I mitt faktiska fall vill jag transformera funktionstyper som deklarerats i ett gränssnitt (från ett tredjepartsbibliotek) och bara ändra returtypen:
interface Foo {
baz<T extends { a?: string, b?: string}>(arg: T): T extends {a: string} ? string : number;
}
type Baz = Foo["baz"]
type PromisifiedBaz = Promisify<Foo["baz"]>
// Only type is relevant so skip implementaion
const baz: Baz = undefined as any;
const promisifiedBaz: PromisifiedBaz = undefined as any;
// CORRECT
const shouldBeNumber = baz({b: "b"});
// CORRECT
const shouldBeString = baz({a: "a", b: "b"});
// CORRECT
const shouldBePromiseNumber = promisifiedBaz({b: "b"});
// WRONG: it's of type Promise<number>
const shouldBePromiseString = promisifiedBaz({a: "a", b: "b"});
Lekplats
Som du kan se fungerar det förutom för den sista shouldBePromiseString. Jag antar att det finns ett problem med typernas inferens (se infer A i Promisify) vilket är anledningen till att returtypen infereras fel.
Hur kan jag skapa en sådan nyttotyp? Är det ens möjligt? Finns det alternativ? Finns det en bättre implementation för Promisify än mitt förslag?