假设我有一个这样的对象:
const person = {
id: 87
name: 'Some Name',
address: {
street: 'Some street',
country: 'Some country'
}
}
Run Code Online (Sandbox Code Playgroud)
我想获得一个所有键值对的并集类型。所以类型应该是:
{ id: number } | { name: string } | { address: { street: string; country: string; } }
Run Code Online (Sandbox Code Playgroud)
那怎么办呢?我试过这个:
type PersonInfo = {
id: number;
name: string;
address: {
street: string;
country: string;
}
}
type PersonMap<M extends { [index: string]: any }> = {
[Key in keyof M]: M[Key]
};
type PersonTest1 = PersonMap<PersonInfo>[keyof PersonMap<PersonInfo>];
// Returns "number | string | { street: string; country: string; }"
type PersonTest2 = PersonMap<PersonInfo>;
// Returns { id: number; name: string; address: { street: string; country: string;} }
Run Code Online (Sandbox Code Playgroud)
如何获得上述联合类型?
似乎您想要一个以下形式的类型函数UnionOfSingleKeyObjects<T>,它将对象类型转换T为单键对象类型的联合,其中每个键keyof T只出现一次。根据您的用例,您可以定义这样的类型函数:
type UnionOfSingleKeyObjects<T extends object> =
{ [K in keyof T]-?: { [P in K]: T[P] } }[keyof T]
Run Code Online (Sandbox Code Playgroud)
并验证它是否按PersonInfo预期工作:
type PersonKVPairs = UnionOfSingleKeyObjects<PersonInfo>
/* type PersonKVPairs = {
id: number;
} | {
name: string;
} | {
address: {
street: string;
country: string;
};
} */
Run Code Online (Sandbox Code Playgroud)
的定义UnionOfSingleKeyObjects是一个映射类型K,其中我们迭代 中的每个键类型keyof T,计算每个键的相关单键对象,然后对其进行索引以keyof T获得所有单键对象类型的并集。
您可以使用分布式条件类型来获得相同的效果,而不是索引到映射类型:
type UnionOfSingleKeyObjects<T extends object> =
keyof T extends infer K ? K extends keyof T ?
{ [P in K]: T[P] } : never : never
Run Code Online (Sandbox Code Playgroud)
无论哪种方式都有效;我倾向于使用映射类型,因为它们比条件类型分布性更容易解释。
在这两种方法中,带有 key 的单键对象都K写为{[P in K]: T[P] }。这也可以写为Record<K, T[K]>使用实用程序Record<K, V>类型,或Pick<T, K>使用实用程序Pick<T, K>类型。这些其他版本有其优点和缺点,并且可能会改变类型在 IntelliSense 快速信息中的显示方式以及输出中可选/readonly键是否保持可选/ 。readonly如果您关心保留这些修饰符并且不想在您的快速信息中看到Pick或,您可以像这样Record编写:{[P in keyof Pick<T, K>]: T[P]}
type UnionOfSingleKeyObjects<T extends object> =
{ [K in keyof T]-?: { [P in keyof Pick<T, K>]: T[P] } }[keyof T]
Run Code Online (Sandbox Code Playgroud)
我们可以看到这样的修饰符被保留了:
type Example = UnionOfSingleKeyObjects<{ a?: string, readonly b: number }>
/* type Example = {
a?: string;
} | {
readonly b: number;
} */
Run Code Online (Sandbox Code Playgroud)
同样,根据您的用例,您可能会也可能不关心这些事情。
| 归档时间: |
|
| 查看次数: |
1017 次 |
| 最近记录: |