从数组类型创建对象类型,其中键是数组中每个对象的属性值

时间:2019-09-23 16:32:56

标签: typescript

给出一个作为对象数组的类型,如何创建一个作为对象的新类型,其中键是数组对象中特定属性的值,而对象的值是一个对象的类型对象泛型。

使用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]这样的东西是行不通的。

1 个答案:

答案 0 :(得分:1)

您可以使用Arr[number]['name']获得数组中所有键的并集,然后可以使用Exatrct从数组中所有可能元素的并集中提取(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;
}

Play