TypeScript: gör en metod av ett generiskt gränssnitt A<T> tillgänglig endast om T är av en viss typ
Var vänlig och titta på denna kod:
interface A<T> {
method1(): A<T>;
}
interface B<T extends Function> extends A<T> {
method2(): B<T>;
}
var foo: A<Function>;
foo.method1();
foo.method2();
Jag förväntade mig att foo skulle vara kompatibel med typen B<Function>, men istället får jag error TS2339: Property 'method2' does not exist on type 'A<Function>'. Kan jag på något sätt skriva om gränssnittet B för att få det att fungera?
Faktiskt försöker jag fixa typningarna för Lodashs _.memoize:
// This should be OK. The type of result1 should be compatible with aFunction.
var result1 = _(aFunction).memoize().value();
// And this should be an error.
var result2 = _(aNonFunctionValue).memoize().value();
UPPDATERING. I princip är min fråga: kan jag skriva en sådan generisk metod för A<T> så att den endast är tillgänglig om T är en underklass av någon annan typ U?
Svar #1
Kan jag skriva om gränssnittet B på något sätt för att få det att fungera?
Lösning
Här är koden:
interface A<T> {
method1(): A<T>;
}
interface B<T extends Function> extends A<T> {
method2(): B<T>;
}
interface A<T> {
method2<T extends Function>(): B<T>;
}
var foo: A<Function>;
foo.method1();
foo.method2(); // works!
Komma fram till lösningen
Låt oss ta ett steg tillbaka och fundera på vad vi vill arbeta med:
var foo: A<Function>;
foo.method2(); // Should work
Detta betyder att A<Function> bör ha method2 på sig. Så:
interface A<T> {
method2<T extends Function>(): B<T>;
}
Och denna metod två lägger till en generell begränsning på T och returnerar något av typen B.
Resten är klar i den slutliga lösningen 🌹
Svar #2
Visade sig att TypeScript inte stödjer detta. Se https://github.com/Microsoft/TypeScript/issues/1290
UPPDATERING 2019: Nu när vi har villkorstyper är det en barnlek:
interface A<T> {
method1(): A<T>;
method2: T extends Function ? () => A<T> : never;
}
declare var foo: A<Function>;
foo.method1();
foo.method2();
