我的代碼中的型別有問題 - 生成聯合型別約束,而不是從ItemProperties型別字典中只選擇一種型別。是否有任何解決方案可以根據 current對props內部屬性進行嚴格限制?ItemConfigItemType
PS 在型別宣告中用元組包裝T泛型(如此處所述)不能解決問題。props
簡化代碼示例:
enum ItemType {
Dog = 1,
Car = 2,
Building = 3,
}
interface ItemProperties {
[Item.Dog]: {
name: string;
};
[Item.Car]: {
power: number;
};
}
interface ItemConfig<T extends ItemType = ItemType> {
type: T;
props: T extends keyof ItemProperties ? ItemProperties[T] : {};
}
const config: ItemConfig[] = [
{
type: ItemType.Dog,
props: ...
}
];
預期typeof props:
{ name: string }
實際typeof props:
{ name: string } | { power: number } | {}
uj5u.com熱心網友回復:
正如評論中所說,問題是ItemConfig等于,{type: ItemType, props: {} | {name: string} | {power: number}}而您希望它是一個有區別的聯合{type: ItemType.Dog, props: {name: string}} | {type: ItemType.Car, props: {power: number}} | .. 來正確鍵入陣列元素props。
創建此聯合的一種方法是使用分布式條件型別(docs):
type ItemConfig<T = ItemType> = T extends ItemType ? {
type: T;
props: T extends keyof ItemProperties ? ItemProperties[T] : {};
} : never
TypeScript 游樂場
因為T條件中的 是裸型別引數,所以ItemConfig<ItemType.Dog | ItemType.Car | ItemType.Building>分配到ItemConfig<ItemType.Dog> | ItemConfig<ItemType.Car> | ItemConfig<ItemType.Building>,這是所需的聯合。
或者(正如 Captain-yossarian 所說),由于ItemTypeextends PropertyKey(ie string | number | symbol),您可以使用映射型別來創建一個物件,該物件具有所需聯合的組成部分作為其值,并索引該物件以獲得聯合:
type ItemConfig = {
[T in ItemType]: {
type: T,
props: T extends keyof ItemProperties ? ItemProperties[T] : {}
}
}[ItemType]
TypeScript 游樂場
這樣做的好處是您不需要ItemConfig泛型引數T,但它僅限于擴展型別PropertyKey(否則您不能將其用作映射型別中的鍵)。
這兩種方法產生相同的ItemConfig聯合,這將允許props為每個陣列元素推斷適當的型別:
const config: ItemConfig[] = [
{
type: ItemType.Dog,
props: {name: 'x'}
// type of props: {name: string}
},
{
type: ItemType.Car,
props: {power: 7}
// type of props: {power: number}
},
{
type: ItemType.Dog,
props: {power: 7} // Type error
// type of props: {name: string}
}
];
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/460179.html
