typescript - 将类型数组简化为单一类型?
问题描述
我正在开发一个定义了规则列表的库。我想把这个规则列表变成一个界面,让一些东西遵守规则。
我最终得到一个与此结构类似的列表:
const rules = [
{} as { foo: 1 | 2 | 3},
{} as { bar: 4 | 5 | 6},
]
type T = typeof rules
最终的类型T
是联合数组,如下所示:
type T = ({
foo: 1 | 2 | 3;
} | {
bar: 4 | 5 | 6;
})[]
但我真正想要的是一个合并它们的界面:
type T = {
foo?: 1 | 2 | 3
bar?: 4 | 5 | 6
}
有什么办法可以做到这一点?
解决方案
您似乎正在尝试:
- 将联合变成交叉点。
- 推断数组中项目的类型。
- 将所有属性设为可选。
如果我们以这种方式分解它们,我们可以一次解决每个问题。
要将联合变成交叉点,您可以检查这个魔法:
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
要推断数组中项目的类型,您可以创建另一个实用程序类型:
type InferArray<T extends any[]> = T extends (infer U)[] ? U : never;
为了使所有属性可选,TS 已经有一个内置的实用程序:
type OptionalAll<T> = Partial<T>;
我们现在可以将它们组合起来:
const rules = [
{} as { foo: 1 | 2 | 3 },
{} as { bar: 4 | 5 | 6 },
];
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
type InferArray<T extends any[]> = T extends (infer U)[] ? U : never;
type T = Partial<UnionToIntersection<InferArray<typeof rules>>>;
检查这里的操场。