【问题标题】:How can infer a type based on a key from an array of typed objects?如何根据类型对象数组中的键推断类型?
【发布时间】:2022-01-05 01:18:58
【问题描述】:

我正在尝试使用其中一个重复(和必需)键创建基于对象数组的类型,但 typescript 无法按我期望的方式处理 Array.map()

const list = [
  {
    _id: 'foo1'
  },
  { _id: 'foo2' }
] as const

const listIds = list.map(listValue => listValue._id)

我希望listIds 被推断为['foo1', 'foo2'],但被视为("foo1" | "foo2")[]。这对我来说没有意义,因为 Array.map 不可能返回与原始数组大小不同的数组。

还有其他方法可以获得我正在寻找的结果吗?

PS。请参阅 TypeScript Playground 示例 here

【问题讨论】:

标签: arrays typescript typescript4.0


【解决方案1】:

对于这种获取特定键值的特定情况,可以使用辅助函数:

const mapByKey = <A extends readonly unknown[], K extends keyof A[number]>(
  array: A,
  key: K
// the -readonly ensures the return type isn't readonly even if the
// input array is
): {-readonly [P in keyof A]: A[P][K]} =>
  array.map((x: A[number]) => x[key]) as {-readonly [P in keyof A]: A[P][K]}

// ['foo1', 'foo2']
const listIds = mapByKey(list, '_id')

Playground link


但是,我认为没有一种简单的方法可以将其推广到任何类型的函数。

我们真正想要的:

declare const map: <A extends readonly unknown[], F>(
  array: A,
  fn: <T extends A[number]>(x: T) => F<T>
): {-readonly [K in keyof A]: F<A[K]>}
// with your example F would be like a generic type like
// type F<T> = T['_id']

但是,这不会编译为 TypeScript lacks higher-kinded types。在 TypeScript 中有各种 hack 来模拟这个,但它们使用起来很麻烦,我个人认为这个问题不值得。

【讨论】:

    猜你喜欢
    • 2022-07-19
    • 2022-08-09
    • 2021-07-24
    • 2020-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 2022-12-18
    相关资源
    最近更新 更多