typescript - Åtkomst till generiska från ärvd typ


Jag försöker få åtkomst till generiska typer från en annan klass, som själv kommer att skickas som en generisk typ.

export default abstract class Foo<K, V> {}
import Foo from './Foo';
export default abstract class Bar<Foo> {}

Hur skulle jag gå till väga för att komma åt K och V inom Bar-klassen? Jag skulle vilja skapa en abstrakt metod som använder dessa typer, men jag är inte säker på hur jag faktiskt skulle komma åt den nästlade generiska typen.

Redigera: Lade till användningsfall för mer förtydligande

Exempel på användningsfall:

export default class Baz extends Foo<string, number> {}
import Baz from './Baz';
export default class Qux extends Bar<Baz> {}

Jag skulle vilja att Bar-klassen känner igen att Qux bör ha generiken <string, number>, eftersom jag vill ha en abstrakt metod inom Bar som följer signaturen

public abstract foo(thing: string): number;

som ett exempel.

Ett alternativ som jag har övervägt: att skicka Baz inom konstruktorn istället för som en generisk typ... Dock finns det fortfarande ett problem med att faktiskt få de generiska typerna från Baz själv.

Redigera 2: Faktiskt användningsfall

Okej, så jag har dessa två klasser.

export default abstract class Storage<K, V> {
    protected abstract _init(): void;
}
import Data from '../structures/bases/Data';
export default class DataStore extends Storage<string, Data> {
    protected async _init(): void {
        // ...
    }
}

Här är där problemen uppstår

import Data from '../structures/bases/Data';
export default class DataHandler extends Handler<DataStore> {
    public abstract get(key: string): Data {
        //...
    }
}
export default abstract class Handler<K, V> {
    // my goal, where K is string and V is Data when DataStore is passed
    public abstract get(key: K): V;
}

Jag kommer att ha flera *Handlers där jag skulle skicka en instans av en utökad Storage som generisk. Nu kan jag uppenbarligen inte magiskt plugga in K och V, vad jag istället kan göra antar jag är att ha Handler<K, V> och sedan skicka <string, Command>, men jag hoppades att jag helt enkelt skulle kunna skicka instansen av *Storage istället för att skicka de 2 typerna igen varje gång.

Svar #1

Din definition av Bar är felaktig. Den borde se ut ungefär så här:

import Foo from './Foo';
export default abstract class Bar<K, V, F extends Foo<K,V>> {}

Din ursprungliga Foo var en typvariabel inuti bar och inte den Foo-klass du vill att det ska vara. Och sedan är K och V bundna till typvariablerna för instansen av Foo. Och nu är alla typvariabler tillgängliga i din Bar-instans

Det här är lite av ett monster, men att använda typvariabler kan snabbt spåra ur.