You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何确保数组包含联合类型所有类型?TypeScript类型校验问题

实现联合类型转全成员元组的类型校验

没问题!要实现让数组必须包含联合类型的所有成员,咱们可以用TypeScript的高级类型技巧来定义UnionToTuple。先明确下需求:我们需要一个类型工具,把联合类型转成包含该联合所有成员的元组——也就是说,数组必须覆盖联合的每一个类型,少一个都会报类型错误,顺序倒是不强制。

核心思路

TypeScript的联合类型本身是无序且自动去重的,所以我们要做的是“收集”联合里的每一个成员,把它们拼成元组。这里会用到两个关键特性:

  • 分布式条件类型:当条件类型作用于联合类型时,会自动拆分联合的每个成员单独处理。
  • 交叉类型的函数推断:通过把联合成员转成函数类型的交叉,再推断出返回值,从而逐个提取联合成员。

具体实现代码

// 辅助类型:把联合类型转成交叉类型
type UnionToIntersection<U> = 
  (U extends any ? (k: U) => void : never) extends (k: infer I) => void 
    ? I 
    : never;

// 核心类型:把联合类型转成包含所有成员的元组
type UnionToTuple<U> = 
  UnionToIntersection<U extends any ? () => U : never> extends () => infer T 
    ? [...UnionToTuple<Exclude<U, T>>, T] 
    : [];

测试示例

咱们用你定义的Colors联合类型来测试:

type Colors = 'red' | 'blue' | 'pink';

// ❌ 错误:缺少'pink',类型不匹配
const colors1: UnionToTuple<Colors> = ['red', 'blue'];

// ✅ 正确:包含所有联合成员
const colors2: UnionToTuple<Colors> = ['red', 'blue', 'pink'];

// ✅ 正确:顺序不影响,只要全包含就行
const colors3: UnionToTuple<Colors> = ['pink', 'red', 'blue'];

简单解释下类型逻辑

  1. UnionToIntersection:先把联合的每个成员转成“参数为该成员的函数”,再把这些函数转成交叉类型。最后通过infer提取出交叉函数的参数类型,得到联合类型的交叉形式——这一步是为了后续能逐个提取成员。
  2. UnionToTuple:把联合的每个成员转成“返回该成员的函数”,再转成交叉类型。通过infer提取这个交叉函数的返回值(也就是联合的某一个成员),然后用Exclude去掉已经提取的成员,递归处理剩下的部分,直到联合类型为空,最后把所有成员拼接成元组。

注意事项

  • 这个实现支持TS 4.0及以上版本,低版本可能会有兼容性问题。
  • 元组的顺序不一定和你定义联合类型的顺序一致,因为TypeScript的联合类型本身是无序的,但只要所有成员都包含在内就符合要求。
  • 如果联合类型里有重复成员(比如'red' | 'red' | 'blue'),生成的元组会自动去重,因为联合类型本身会去重。

内容的提问来源于stack exchange,提问作者Samuel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 16:07:50