TypeScript 字典中的类型推断

时间:2021-07-17 19:30:12

标签: typescript

想象一个汽车商店建模的虚构示例:

type Vehicle<TClass extends string, TSpecs> = {
    class: TClass,
    specs: TSpecs
}

type Truck =     Vehicle<'truck',      { horsePower: number, maxLoad: number }>
type MotorBike = Vehicle<'motor-bike', { maxSpeed: number }>
type Boat =      Vehicle<'boat',       { name: string, type: 'fishing' | 'cargo' }>

type SalesCatalog<TClasses extends string> = {
    [vehicleClass in TClasses]: Vehicle<vehicleClass, any>[]
}

我可以通过以下方式创建示例商店:

let localStore: SalesCatalog<'truck' | 'boat'> = {
    boat: [
        { class: "boat", specs: { name: 'Gunnar', type: 'fishing' } },
        { class: "boat", specs: { name: 'Titanic', type: 'cargo' } }
    ],
    truck: [
        { class: 'truck', specs: { horsePower: 300, maxLoad: 5000 } }
    ]
}

我从 TypeScript 中获得两个好处:

  • 联合类型 'truck' | 'boat' 确保 localStore 必须包含两个键
  • 字典的键与包含的值对齐。所以前。键 class: "boat" 下只允许带有 boat 的对象。

然而,specs 属性仍然是 any 类型,我找不到方法告诉 TypeScript,boat 类推断 {{1} } 在 { name: string, type: 'fishing' | 'cargo' } 中。理想情况下,我想通过

声明 SalesCatalog
SalesCatalog

但这行不通。所以我的问题是:有可能吗..?

1 个答案:

答案 0 :(得分:2)

如果不使用具体的类,就无法判断哪个规范属于哪个类,所以你能做的最好的事情就是使用它们:

type SalesCatalog<T extends Truck|MotorBike|Boat> = {
  [vehicleClass in T['class']]:  (T&{class:vehicleClass})[]
}

有了这个,您可以使用 SalesCatalog<Truck|Boat> 并对规范进行适当的类型检查