[英]In typescript, How to use a generic to constraint and describe return value type of function?
[英]How to describe constraint using conditional type which is based on generic type?
我在代码中输入时遇到问题 - 生成了联合类型约束,而不是仅从ItemProperties
类型字典中选择一种类型。 是否有任何解决方案可以根据当前ItemType
对ItemConfig
中的props
属性进行严格约束?
PS 在props
类型声明中用元组包装T
generic(如此处所述)不能解决问题。
简化代码示例:
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 } | {}
如评论中所述,问题在于ItemConfig
等于{type: ItemType, props: {} | {name: string} | {power: number}}
{type: ItemType, props: {} | {name: string} | {power: number}}
{type: ItemType, props: {} | {name: string} | {power: number}}
而你会希望它成为一个有区别的联合{type: ItemType.Dog, props: {name: string}} | {type: ItemType.Car, props: {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
因为条件中的T
是一个裸类型参数, ItemConfig<ItemType.Dog | ItemType.Car | ItemType.Building>
ItemConfig<ItemType.Dog | ItemType.Car | ItemType.Building>
ItemConfig<ItemType.Dog | ItemType.Car | ItemType.Building>
分发到ItemConfig<ItemType.Dog> | ItemConfig<ItemType.Car> | ItemConfig<ItemType.Building>
ItemConfig<ItemType.Dog> | ItemConfig<ItemType.Car> | ItemConfig<ItemType.Building>
ItemConfig<ItemType.Dog> | ItemConfig<ItemType.Car> | ItemConfig<ItemType.Building>
,这是所需的联合。
或者(如 captain-yossarian 所说),由于ItemType
扩展了PropertyKey
(即string | number | symbol
),您可以使用映射类型创建一个 object ,它具有所需联合的成分作为其值,并索引该 object 以获得工会:
type ItemConfig = {
[T in ItemType]: {
type: T,
props: T extends keyof ItemProperties ? ItemProperties[T] : {}
}
}[ItemType]
这样做的好处是您不需要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}
}
];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.