首页 > 解决方案 > 从数组类型创建对象类型,其中键是数组中每个对象中的属性值

问题描述

给定一个对象数组的类型,我如何创建一个新的对象类型,其中键是数组对象中特定属性的值,对象的值是其中一个对象的类型仿制药。

使用 JS 代码,它看起来像这样:

const obj = arr.reduce((acc, element) => ({
  ...acc,
  [element.name]: element.bar
}))

到目前为止,我有这个:

type ArrayToObject<Arr extends Array<CustomType<any>> = []> = {
  [K in keyof Arr]: ExtractCustomTypeGeneric<Arr[K]>
}

type ExtractCustomTypeGeneric<A> = A extends CustomType<infer T> ? T : never;

type CustomType<T> = {
  name: string,
  foo: number,
  bar: T
}

这给了我一个数组对象(因为K in keyof Arr是索引号),而我希望属性键是name. 不幸的是,类似[Arr[K]['name'] for K in keyof Arr]的东西不起作用。

标签: typescript

解决方案


您可以使用 获取数组中所有键的联合Arr[number]['name'],然后您可以使用Extract从数组中所有可能元素的联合中提取 ( Arr[number]) 仅具有当前映射的项目name

type ArrayToObject<Arr extends Array<CustomType<any>> = []> = {
  [K in Arr[number]['name']]: ExtractCustomTypeGeneric<Extract<Arr[number], { name: K }>>
}

type ExtractCustomTypeGeneric<A> = A extends CustomType<infer T> ? T : never;

type CustomType<T, K = string> = {
  name: K,
  bar: T
}

function createItems<T extends Array<CustomType<any, K>>, K extends string>(...a: T) : T{
    return a;
}

let a = createItems({ name: "A", bar: ""}, { name: "B", bar: 0})

type R = ArrayToObject<typeof a>
//Same as 
type R = {
    A: string;
    B: number;
}


推荐阅读