通過在交集中混合 TypeScript 型別和介面,我似乎在我的代碼中放松了介面的更嚴格的行為。我希望能夠使用交叉點組合型別(這樣我可以在特定實體中縮小型別的范圍),但我希望能夠保持介面的準確性。
拿這個代碼:
type Vehicle = {
name: string
properties: Record<string, unknown>
}
interface CarProperties {
electric?: boolean
}
type Car = Vehicle & {
name: 'car'
properties: CarProperties
}
const car: Car = {
name: 'car',
properties: {
electric: false,
someOther: 'bs' // <= I want this to throw a TS Error
}
}
由于CarProperties是一個介面,我希望它不允許包含someOther密鑰。
為什么不是這樣?否則,人們將如何實作同樣的目標?
uj5u.com熱心網友回復:
問題是交集型別Car。這導致propertiescar 成為 aRecord<string, unknown> & CarProperties并因此允許字串鍵。
為了實作你想要的,你可以為你的 Vehicle 型別添加一個泛型:
type Vehicle<T extends object> = {
name: string
properties: T
}
type GenericVehicle = Vehicle<Record<string, unknown>>;
interface CarProperties {
electric?: boolean
}
interface Car extends Vehicle<CarProperties> {
name: 'car'
}
PS:我注意到你稱之為“聯合型別”,它不是。交集型別共享相交型別的屬性,而聯合型別可以是聯合型別之一。
uj5u.com熱心網友回復:
您可以使electric屬性成為必需的,并使用objecttype 而不是Record<string, unknown>。
type Vehicle = {
name: string
properties: object, // <---- change
}
type CarProperties = {
electric: boolean // is required now
}
type Car = Vehicle & {
name: 'car'
properties: CarProperties
}
// ok
const car2: Car = {
name: 'car',
properties: {
electric: false,
}
}
// expected error
const car4: Car = {
name: 'car',
properties: []
}
// expected error
const car5: Car = {
name: 'car',
}
// error
const car3: Car = {
name: 'car',
properties: {}
}
// error
const car: Car = {
name: 'car',
properties: {
electric: false,
someOther: 'bs' // error
}
}
我知道,object由于這條規則,使用型別有點爭議,但是您可以在此答案中找到有關優缺點的更多資訊。
如果您有更多的變體Vehicle,而不僅僅是一個Car,您可能希望properties從Vehicletype 中洗掉并創建一個可區分的 allowed 聯合Vehicles。這只是我的猜測,因為我不知道任何其他要求。
還值得了解超額財產檢查。它不允許您為文字引數提供任何其他額外的屬性。
如果您將所有要求和測驗用例放入問題中,我相信您會得到您想要的
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/359819.html
標籤:javascript 打字稿 类型 范畴论 联合类型
下一篇:需要的SQL查詢邏輯
