是否可以创建映射条件类型,使得诸如
的任何类型interface Car {
color: string
max_speed: number
doors: number
}
type CarPorperties = SomeMappedAndConditiomalType<Car>
将导致
type CarProperties =
{color: string}
|{max_speed: number}
|{doors: number}
答案 0 :(得分:3)
事实证明这是可能的:将属性类型映射到{ __tag: k, [k]: T[k] }
之类,然后采用这些类型的并集。这样就给出了标记的联合类型,其中__tag
属性是判别式。
用法示例:
interface Car {
color: string
max_speed: number
doors: number
}
type Test = ObjectToTaggedUnion<Car>
/*
* Test = { __tag: 'color', color: string }
* | { __tag: 'max_speed', max_speed: number }
* | { __tag: 'doors', doors: number }
*/
下面的实现。详细信息有些棘手,因为Typescript很难使对象类型变得简单,其中__tag
属性是直接命名的,而k
属性却不是这样。
type ObjectToTaggedUnion<T> = {
[K in keyof T]: K extends string
? { [kk in K | '__tag']: kk extends '__tag' ? K : T[K] }
: never
}[keyof T];
答案 1 :(得分:2)
您想要做的是将产品类型拆分为总和类型。我认为这是不可能的,您可以分别使用键和值,但是看起来无法实现配对。
但是我们可以采取另一种方法。因此,我们可以从代表每个属性的类型开始,并通过&
和|
// single props types
type ColorProp = { color: string }
type MaxSpeedProp = { max_speed: number }
type DoorsProp = { doors: number }
type Car = ColorProp & MaxSpeedProp & DoorsProp // product
type CarProps = ColorProp | MaxSpeedProp | DoorsProp // sum
// we can build Car directly as it would be orginal interface
const car: Car = {
color: 'color',
max_speed: 1,
doors: 2
}
// or create it by merging props types instances
const doors: DoorsProp = { doors: 2 };
const max_speed: MaxSpeedProp = { max_speed: 2 };
const color: ColorProp = { color: 'red' };
const car2: Car = {
...doors,
...color,
...max_speed
}
通过这种方式,您可以组合较小的类型-将类型道具化为较大的复合物-总和和乘积。