【问题标题】:Generic function picking one property选择一个属性的通用函数
【发布时间】:2022-11-04 19:37:37
【问题描述】:

我试图通过仅过滤一个属性来创建一个通用函数来转换对象 - 沿着以下几行:

function pickOnePropertyUntyped(data: any, key: any): any {
  return {
    [key]: data[key]
  }
}

因此,期望的行为是:

const a: A = {
  a: 'a',
  b: 1
}
const r = pickOnePropertyUntyped(a, 'a'); // {'a': 'a'}

我在获取所需类型和实现方面遇到问题。

我的尝试是:

type UnionToIntersection<U> = 
    (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never 

type NoUnion<Key> =
    [Key] extends [UnionToIntersection<Key>] ? Key : never; 

type PickOneProperty<T, P extends keyof T & string> = {
  [K in keyof T as K extends NoUnion<P> ? K : never]: T[K]
}

function pickOneProperty<T, K extends keyof T & string>(
   data: T,
   key: K,
): PickOneProperty<T, K> {
  return {
    [key]: data[key]
  }
}

哪个:

不幸的是,它将返回类型标记为不正确。

Playground

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您在这里观察到的或多或少是 TypeScript 中缺少的功能。大多数情况下,当您尝试使用计算属性键时,TypeScript 会自动添加一个索引签名到对象的类型。只有一些例外;例如,当密钥的类型已经是已知的字符串字面量类型(as shown here)。请参阅有关此问题的讨论 here

    索引签名打破了这里的打字。据我所知,没有“满意”这个问题的解决方案。正如 TypeScript 所见,即使是普通的类型断言在这里也不起作用没有重叠两种类型之间。您可以做的是先声明unkown,然后再声明PickOneProperty&lt;T, K&gt;

    function pickOneProperty<T, K extends keyof T & string>(
       data: T,
       key: K,
    ): PickOneProperty<T, K> {
      return {
        [key]: data[key]
      } as unknown as PickOneProperty<T, K>
    }
    

    请注意,现在这个实现中几乎没有类型安全。


    Playground

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-29
      • 1970-01-01
      • 2017-03-24
      • 2021-05-30
      • 2017-12-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多