首页 > 解决方案 > 将类型数组简化为单一类型?

问题描述

我正在开发一个定义了规则列表的库。我想把这个规则列表变成一个界面,让一些东西遵守规则。

我最终得到一个与此结构类似的列表:

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
}

有什么办法可以做到这一点?

标签: typescript

解决方案


您似乎正在尝试:

  1. 将联合变成交叉点。
  2. 推断数组中项目的类型。
  3. 将所有属性设为可选。

如果我们以这种方式分解它们,我们可以一次解决每个问题。

要将联合变成交叉点,您可以检查这个魔法

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>>>;

检查这里的操场


推荐阅读