typescript - Hur gör man ett generiskt funktionsvärde?
Överväg följande kod:
interface Foo<T1> {
foo: string;
baz: T1;
}
function toFoo<T2>(value: T2): Foo<T2> {
return {
foo: 'bar',
baz: value
};
}
// Actually this function is imported from an NPM package so I can't change it
// The example is given for a better illustration
function memoize<T3, T4>(func: (arg: T3) => T4): (arg: T3) => T4 {
// Some implementation...
return func;
}
const memoizedToFoo: {<T5>(value: T5): Foo<T5>} = // ???
Funktionen toFoo är en generisk. Jag behöver göra en memoiserad version av toFoo som också är generisk. Jag kan inte ändra typen och implementeringen av memoize. Hur implementerar man memoizedToFoo så att den matchar det givna gränssnittet?
Jag försöker detta, men det fungerar inte:
const memoizedToFoo<T5> = memoize(toFoo<T5>); // unexpected <T5>
Svar #1
Kan du ändra din memorize()-funktion? Den arbetar för hårt.
Följande kommer automatiskt att härleda rätt typ:
interface Foo<T1> {
foo: string;
baz: T1;
}
function toFoo<T2>(value: T2): Foo<T2> {
return {
foo: 'bar',
baz: value
};
}
function memoize<F extends Function>(func: F): F {
// Some implementation...
return func;
}
const memoizedToFoo = memoize(toFoo)
Lekplatslänk
UPPDATERING: Eftersom du inte kan ändra memorize(), kan du skriva över det på ett snyggt sätt enligt följande:
// memorize.ts
import { memoize as origMemoize } from 'memoize'
// or if it is commonJS
import origMemoize from 'memoize'
export const memoize = origMemoize as <F extends Function>(func: F) => F
Då kan du använda det precis som originalet:
import { memoize } from './memoize'
// code away
Observera att denna lösning kompromissar med viss typkontroll eftersom F inte är begränsad till (arg: X) => Y
För att ta itu med detta på rätt sätt behöver vi: https://github.com/Microsoft/TypeScript/pull/22368
Svar #2
Gör den memoiserade funktionen med any-generiskt argument (om det behövs) och konvertera den till den generiska funktionstypen:
const memoizedToFoo: <T5>(value: T5) => Foo<T5> = memoize(toFoo);
// or
const memoizedToFoo: typeof toFoo = memoize(toFoo);
