繁体   English   中英

如何使用基于泛型类型的条件类型来描述约束?

[英]How to describe constraint using conditional type which is based on generic type?

我在代码中输入时遇到问题 - 生成了联合类型约束,而不是仅从ItemProperties类型字典中选择一种类型。 是否有任何解决方案可以根据当前ItemTypeItemConfig中的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

TypeScript 操场

因为条件中的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]

TypeScript 操场

这样做的好处是您不需要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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM