javascript - Hur man implementerar ett gränssnitt med villkorliga typer i TypeScript
I ett personligt projekt stöter jag på ett problem med TypeScript villkorade typer. Jag har grundläggande förståelse för villkorade typer från TypeScript-dokumentationen. Jag skulle förvänta mig att inställningen nedan fungerar men den ger ett typerrorsmeddelande.
I grund och botten försöker jag definiera ett gränssnitt för en trädnod som laddas från disken. Detta innebär att vissa noder kanske inte är korrekt laddade på grund av saknade filer etc. Så varje nodimplementation innehåller antingen Content eller Error.
interface Content {
data: number;
}
interface Error {
code: string;
}
export interface TreeNode<T extends Content | Error> {
getValue(): T extends Content ? number : string;
}
class ValueNode<ValueType extends Content> implements TreeNode<ValueType> {
private readonly value: number;
public constructor(value: number) {
this.value = value;
}
public getValue(): number {
return this.value;
}
}
Jag skulle förvänta mig att implementeringen av getValue-metoden skulle tillåtas returnera string eftersom gränssnittet implementeras med typ som utökar Content. Men jag får istället detta typfel:
Egenskapen
getValuei typenValueNode<ValueType>kan inte tilldelas samma egenskap i basklassenTreeNode<ValueType>.
Typen
() => numberkan inte tilldelas till typen() => ValueType extends Content ? number : string.
- Typ
numberkan inte tilldelas typValueType extends Content ? number : string- Typ
() => numberkan inte tilldelas typen() => ValueType extends Content ? number : string.- Typ
numberkan inte tilldelas typenValueType extends Content ? number : string
Tydligt gör jag det på fel sätt. Vad skulle vara det rätta sättet att uppnå mitt mål?
Svar #1
Som @Dai påpekade är det bättre att inte skugga den inbyggda
Error-typen (så att du kan använda den i din modul).
Här är två alternativ:
TS Playground-länk
interface ContentValue {
data: number;
}
interface ErrorValue {
code: string;
}
export interface ValueGetter<T> {
getValue(): T;
}
class ValueNode<T extends ContentValue> implements ValueGetter<ContentValue['data']> {
public constructor(private readonly value: T) {}
public getValue(): number {
return this.value.data;
}
}
// or
class SimpleValueNode<T extends ContentValue> {
public constructor(private readonly value: T) {}
public getValue(): number {
return this.value.data;
}
}
