如何使用TypeScript将对象类型的数组转换为平面对象类型



如何将对象数组类型转换为平面对象类型?例如:

type T1 = [{
base: string;
}, {
hover: any;
}]
type T2 = ConvertToFlat<T1>

T2为

{
base: string;
hover: any;
}

ConvertToFlat内部是什么?

打字游戏场

这样做了,但不是很漂亮:

type ConvertToUnion<U> = U extends Array<infer X> ? {[K in keyof X]:X[K]} : never
type ConvertToIntersection<U extends {[K:string]: any}> = (U extends any ? (x:U)=>void : never) extends (x:infer X)=>void ? X : never
type ConvertToFlat<T> = ConvertToIntersection<ConvertToUnion<T>>

第二种是基于这个后

游乐场

以下是我的想法:

type T1 = [
{
base: string
},
{
hover: any
}
]
type ConvertToFlat<T extends any[]> = T['length'] extends 0
? {}
: ((...b: T) => void) extends (a, ...b: infer I) => void
? { [P in keyof T[0]]: T[0][P] } & ConvertToFlat<I>
: []
type T2 = ConvertToFlat<T1>
// inferred type of T2 = { base: string } & { hover: any }

下面的代码应该做你想做的事情,但我认为由于这个悬而未决的问题,它不能正确推断。

// Names of properties in T with types that include undefined
type OptionalPropertyNames<T> = { [K in keyof T]: undefined extends T[K] ? K : never }[keyof T]
// Common properties from L and R with undefined in R[K] replaced by type in L[K]
type SpreadProperties<L, R, K extends keyof L & keyof R> = {
[P in K]: L[P] | Exclude<R[P], undefined>
}
type Id<T> = { [K in keyof T]: T[K] } // see note at bottom*
// Type of { ...L, ...R }
type Spread<L, R> = Id<
// Properties in L that don't exist in R
Pick<L, Exclude<keyof L, keyof R>> &
// Properties in R with types that exclude undefined
Pick<R, Exclude<keyof R, OptionalPropertyNames<R>>> &
// Properties in R, with types that include undefined, that don't exist in L
Pick<R, Exclude<OptionalPropertyNames<R>, keyof L>> &
// Properties in R, with types that include undefined, that exist in L
SpreadProperties<L, R, OptionalPropertyNames<R> & keyof L>
>

type ConvertToFlat1<T extends any[]> = T['length'] extends 0
? {}
: ((...b: T) => void) extends (a, ...b: infer I) => void
? Spread<{ [P in keyof T[0]]: T[0][P] }, ConvertToFlat1<I>>
: []
type T22 = ConvertToFlat1<T1>

注意我已经从这里复制了其中一些片段:

  1. Typescript:从元组类型中删除条目
  2. Typescript,合并对象类型

这也是一个解决方案:

UnionToIntersection<T>基于类似问题的jcalz答案

type UnionToIntersection<U> = (U extends any
? (k: U) => void
: never) extends ((k: infer I) => void)
? I
: never;
type KeysOf<T extends any[]> = Exclude<keyof T, keyof []>
type ValuesOf<T> = T[keyof T];
type Flatten<T extends any[]>  = UnionToIntersection<ValuesOf<Pick<T, KeysOf<T>>>>;

链接到操场

最新更新