type A = {
a: {
b: string
c: string
}
x: {
y: number
z: number
}
}
我想:
type B = {
b: string
c: string
y: number
z: number
}
... 通过泛型实现
type B = Unfold<A>
如何做到这一点?
答案 0 :(得分:2)
首先,我们需要获取 A
(或任何类似 A
的通用对象)的每个键的值:
type GetValues<T extends {[key: string]: any}> = T[keyof T];
这个泛型让我们传入一个类似 A
的对象,并在 A
的每个键处生成所有对象的 union。出于演示目的,让我们使用它来声明一个基于 Foo
的新类型 A
:
type Foo = GetValues<A>;
如果我们将鼠标悬停在 Foo
上,我们将看到它代表的类型 - 如上所述,A
的每个键处的所有对象的并集。
这很接近,但我们不想要联合,我们想要所有可能类型的 intersection,根据您的要求。幸运的是,SO 上的 this post 已经解决了将联合转换为交集的问题。
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never;
现在我们拥有了我们需要的一切,我们可以构建我们最终的泛型 Unfold<T>
来组成这两个位:
type Unfold<T extends {[key: string]: any}> = UnionToIntersection<GetValues<T>>;
现在我们可以使用 Unfold<T>
将任何类似 A
的类型定义转换为其“展开”版本:
type UnfoldedA = Unfold<A>;
const foobar: UnfoldedA = {b: '', c: '', y: 0, z: 0};
答案 1 :(得分:2)
我希望 smbd 会想出一些更具可读性的东西 ))
type A = {
a: {
b: string
c: string
}
x: {
y: number
z: number,
w: {
u: number
}
}
}
type Primitives = string | number | boolean | symbol
/**
* Get all valid nested pathes of object
*/
type AllProps<Obj, Cache extends Array<Primitives> = []> =
Obj extends Primitives ? Cache : {
[Prop in keyof Obj]:
| [...Cache, Prop] // <------ it should be unionized with recursion call
| AllProps<Obj[Prop], [...Cache, Prop]>
}[keyof Obj]
// credits goes to https://stackoverflow.com/a/50375286
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never;
/**
* Iterate through each array of nested keys
* and get last Prop/Value
*/
type Util<Obj, Props extends ReadonlyArray<Primitives>> =
Props extends []
? Obj
: Props extends [infer First]
? First extends keyof Obj
? Obj[First] extends Primitives ? Record<First, Obj[First]> : {}
: never
: Props extends [infer Fst, ...infer Tail]
? Fst extends keyof Obj
? Tail extends string[]
? Util<Obj[Fst], Tail>
: never
: never
: never
type Unfold<T> = UnionToIntersection<Util<A, AllProps<T>>>
type Result = Unfold<A>
关于 AllProps
和 Util
实用程序的说明,您可以找到 in my blog 和