简体   繁体   English

如何根据类型对象数组中的键推断类型?

[英]How can infer a type based on a key from an array of typed objects?

I'm trying to create a type based on an array of objects using one of the recurring (and required) keys, but typescript doesn't handle Array.map() the way I expect:我正在尝试使用重复(和必需)键之一创建基于对象数组的类型,但是 typescript 没有按我期望的方式处理Array.map()

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

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

I expect listIds to be inferred as ['foo1', 'foo2'] but is instead treated as ("foo1" | "foo2")[] .我希望listIds被推断为['foo1', 'foo2']但被视为("foo1" | "foo2")[] This doesn't make sense to me since it's impossible for Array.map to return an array of a different size than the original array.这对我来说没有意义,因为Array.map不可能返回与原始数组不同大小的数组。

Is there another way to get the results I'm looking for?还有其他方法可以得到我正在寻找的结果吗?

PS. PS。 See TypeScript Playground sample here .请参阅此处的 TypeScript 游乐场样本。

For this specific case of getting the value of a specific key, a helper function can be used:对于获取特定键值的这种特定情况,可以使用帮助程序 function:

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 游乐场链接


However, I don't think there's a simple way of generalising this for any kind of function.但是,我认为对于任何类型的 function 都没有简单的方法来概括这一点。

What we really want:我们真正想要的:

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']

However, this doesn't compile as TypeScript lacks higher-kinded types .但是,这不会编译为TypeScript 缺少更高种类的类型 There are various hacks for emulating this in TypeScript, but they're cumbersome to use and I don't personally think it's worth it for this problem.在 TypeScript 中有各种 hack 可以模拟这个,但它们使用起来很麻烦,我个人认为这个问题不值得。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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