Hur definierar man ett komplext trädstruktursgränssnitt i TypeScript?
Jag hade lärt mig några typiska gränssnitt för enkel trädstruktur, som:
export type Tree<T> = T & {
children?: T[];
}
Men orolig när bladnodens attribut skiljer sig från föräldranodens attribut.
I min användningssituation:
Föräldranod har ett attribut:
groupNameBladnod har två attribut:
fileNameochuniqueId
Så jag definierar trädstrukturen så här:
export type Tree = {
isGroup: true;
groupName: string;
children: Tree[];
} | {
isGroup: false;
fileName: string;
uniqueId: number;
}
Enligt min åsikt finns det 2 nackdelar med denna typ av trädstruktur:
Det är nödvändigt att noggrant fastställa om varje nod är
Groupi rekursiv traversal. Däremot är det bättre att noggrant avgöra det endast medchildren. (det ser ut som omisGroupär lite redundant)Inga mallbokstavstyper
Finns det ett bättre sätt att hantera detta scenario?
Svar #1
Jag skulle ha hanterat det så här:
export type Branch = {
children: Tree[];
};
export type Twig = {
fileName: string;
uniqueId: number;
};
type Either<X, Y> =
| ({
[KX in keyof X]: X[KX];
} & {
[KY in Exclude<keyof Y, keyof X>]?: never;
})
| ({
[KY in keyof Y]: Y[KY];
} & {
[KX in Exclude<keyof X, keyof Y>]?: never;
});
export type Tree = Either<Branch, Twig>;
På det här sättet behöver du inte isGroup, vilket som du påpekade är överflödigt. Och det kommer att säkerställa att det inte finns några objekt som har egenskaper från båda på det här sättet
const tree: Tree = {
fileName: "",
children: [
{
fileName: "",
uniqueId: 1,
}
]
}
och Exclude är nödvändig om båda typerna har gemensamma egenskaper
TS lekplats exempel
