【问题标题】:allow only one property in mapped type在映射类型中只允许一个属性
【发布时间】:2020-08-19 16:44:54
【问题描述】:

可以说有这种类型:

type A = {
  prop1: string;
  prop2: string;
}

可以构造一个类型B,这样A所有属性必须在B中,如下所示:

type B = {
  [k in keyof A]: number
}

但是我如何构造B,使得A 的一个属性 必须存在?

【问题讨论】:

  • 我不认为有办法做到这一点。为此,您需要一种在联合中“分离”元素的方法,我的意思是,keyof A 是字符串的联合,您想从中获取一个字符串,我认为这是不可能的。如果您确切知道A 中的属性,您可以联合{ prop1: number } | { prop2: number },否则我会说这是不可能的
  • 看来this的答案可以给你你想要的。

标签: typescript mapped-types


【解决方案1】:

好的,所以我们可以做到,但它不是微不足道的。最简单的就是找出我们的类型是否至少有一个键。

type AtLeastOneProp<X, Pattern> = (keyof X & keyof Pattern) extends never ? never : X
// use
type B = AtLeastOneProp<{x: string}, {x: string, y: string}> // ? correct has at least one prop - x
type C = AtLeastOneProp<{w: string}, {x: string, y: string}> // ?  never as has no props
type D = AtLeastOneProp<{x: string, y: number, z: number}, {x: string, y: string}> // ? ok has more than one prop

我们在这里所做的是检查键的交集是否给出任何结果。如果是,我们返回原始类型。

更难的是强制我们的类型中只能存在一个键。

type IsSingleVariantOrMore<U extends PropertyKey, Result extends 0 | 1 | 'more' = 0, NextResult extends 0 | 1 | 'more' = Result extends 0 ? 1 : Result extends 1 ? 'more' : 'more'> = 
  ({
    [K in U]: Exclude<U, K> extends never ? NextResult : IsSingleVariantOrMore<Exclude<U, K>, NextResult>
  })[U]
type HasOnlyOneProp<X, Pattern> = IsSingleVariantOrMore<keyof X & keyof Pattern> extends 1 ? X : never;
// use
type E = HasOnlyOneProp<{x: string, z: number}, {x: string, y: string}>; // ? correct has only x 
type F = HasOnlyOneProp<{x: string, y: number}, {x: string, y: string}>; // ? wrong it has two props D is never

我在这里所做的是使用IsSingleVariantOrMore 来计算我们是否有包含一个或多个可能元素的变体。函数HasOnlyOneProp 只是检查我们是否有1,如果有,则意味着类型只有一个共同的道具,任何其他结果意味着该类型没有相交的道具或有多个。

完整代码在the playground

【讨论】:

  • 哇,这是个好主意!我想我需要一些时间来完全理解这里发生了什么……
  • 我承认这很复杂,但它确实可以工作:) 谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 2013-05-31
  • 1970-01-01
相关资源
最近更新 更多