在 TypeScript (v4.5.4) 中,我試圖通過索引簽名來定義物件型別。我希望 TypeScript 強制物件中的某些子屬性具有匹配的型別,但這些型別允許在頂級屬性之間變化。
在下面的(非作業)示例中,我希望所有快樂的司機駕駛他們最喜歡的汽車型別。駕駛員最喜歡的汽車型別與其汽車的實際型別不匹配會導致 TypeScript 編譯器錯誤。
type CarType = 'Minivan' | 'Sports car' | 'Sedan' ; // | 'Pickup truck' |, etc. Imagine this union type has many possible options, not just three.
type Car = {
carType: CarType
// A car probably has many additional properties, not just its type, but those are left out of this minimal example.
// The solution should be resistant to adding additional properties on `Car` (and the `Driver` type below).
};
type Driver = {
favoriteCarType: CarType
car: Car
};
/**
* Happy drivers drive their favorite car type.
*/
const happyDrivers: { [name: string]: Driver } = {
alice: {
favoriteCarType: 'Minivan',
car: {
carType: 'Minivan', // ? Alice drives her favorite type of car.
},
},
bob: {
favoriteCarType: 'Sports car',
car: {
carType: 'Sedan', /* ? Bob doesn't drive his favorite type of car!
This currently does not throw a compiler error because my types are too permissive, but I want it to. */
},
},
};
我已經嘗試以我能想到的所有方式將泛型應用于索引簽名和/或Carand/orDriver型別,但我無法讓編譯器強制執行驅動程式必須與其'sfavoriteCarType完全匹配的約束。carcarType
你能幫我嗎?
uj5u.com熱心網友回復:
您正在尋找的是以下工會:
type Driver = {
favoriteCarType: "Minivan";
car: {
carType: "Minivan";
};
} | {
favoriteCarType: "Sports car";
car: {
carType: "Sports car";
};
} | {
favoriteCarType: "Sedan";
car: {
carType: "Sedan";
};
}
如果您使用Car泛型(汽車的型別作為型別引數),您可以生成此聯合,并且我們使用自定義映射型別來創建聯合的每個組成部分(然后將聯合索引回傳到生成的映射型別):
type Car<T extends CarType = CarType> = { carType: T };
type Driver = {
[P in CarType]: {
favoriteCarType: P
car: { carType: P }
}
}[CarType];
游樂場鏈接
uj5u.com熱心網友回復:
Titian 的回答通過使用映射型別使我走上了正確的道路。請參閱HappyDriver下面的型別。
type CarType = 'Minivan' | 'Sports car' | 'Sedan' ; // | 'Pickup truck' |, etc. Imagine this union type has many possible options, not just three.
type Car = {
carType: CarType
// A car probably has many additional properties, not just its type, but those are left out of this minimal example.
// The solution should be resistant to adding additional properties on `Car` (and the `Driver` type below).
};
/**
* A driver may drive a car of any type, not just their favorite.
*/
type Driver = {
favoriteCarType: CarType
car: Car
};
/**
* A happy driver drives their favorite type of car.
*/
type HappyDriver = {
[C in CarType]: {
[K in keyof Driver]: Driver[K] extends Car
? { [K2 in keyof Car]: Car[K2] extends CarType
? C
: Car[K2]
} : Driver[K] extends CarType
? C
: Driver[K]
}
}[CarType]
const happyDrivers: { [name: string]: HappyDriver } = {
alice: {
favoriteCarType: 'Minivan',
car: {
carType: 'Minivan', // ? Alice drives her favorite type of car.
},
},
bob: {
favoriteCarType: 'Sports car',
car: {
carType: 'Sedan', /* ?? Bob doesn't drive his favorite type of car, so this line causes a compiler error, which is what we want to happen. */
},
},
};
游樂場鏈接。
無論如何,我已將提香的答案標記為正確答案,因為它幫助我找到了我正在尋找的答案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/426090.html
