Vyhledávání na webu

TypeScript: zpřístupnit metodu generického rozhraní A<T> pouze tehdy, pokud je T určitého typu


Podívejte se prosím na tento kód:

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();

Očekával jsem, že foo bude kompatibilní s typem B<Function>, ale místo toho dostanu error TS2339: Property 'method2' does not exist on type 'A<Function>'. Můžu nějak přepsat rozhraní B, aby to fungovalo?

Vlastně se snažím opravit typování pro _.memoize v lodashu:

// 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();

AKTUALIZACE. V zásadě je moje otázka: mohu napsat takovou generickou metodu pro A<T>, která bude dostupná pouze tehdy, pokud T je podtypem nějakého jiného typu U?

Odpověď č. 1

Mohu nějak přepsat rozhraní B, aby to fungovalo?

Řešení

Zde je kód:

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!

Dosažení řešení

Pojďme se na chvíli zastavit a zamyslet se, co chceme dělat:

var foo: A<Function>;
foo.method2(); // Should work

To znamená, že A<Function> by na něm měl mít method2. Takže:

interface A<T> {
    method2<T extends Function>(): B<T>;
}

A tato metoda dva přidává generické omezení na T a vrací něco typu B.

Zbytek je jasný v konečném řešení 🌹

Odpověď č. 2

Ukazuje se, že TypeScript to nepodporuje. Viz https://github.com/Microsoft/TypeScript/issues/1290

AKTUALIZACE 2019: Teď, když máme podmíněné typy, je to hračka:

interface A<T> {
    method1(): A<T>;
    method2: T extends Function ? () => A<T> : never;
}

declare var foo: A<Function>;
foo.method1();
foo.method2();