如何在TypeScript中创建包含联合类型所有成员的严格数组类型?
实现包含联合类型所有成员的严格数组类型
给定联合类型:
type MyUnion = 'foo' | 'bar' | 'baz';
需要创建StrictArrayOfUnion类型,实现以下效果:
- 数组必须包含联合类型的所有成员,顺序无关;
- 缺少任意成员、包含重复成员(导致缺少其他成员)、包含非法成员的数组都会触发类型报错。
示例代码:
type MyStrictUnionType = StrictArrayOfUnion<MyUnion>; // 合法示例 const a: MyStrictUnionType = ['foo', 'bar', 'baz']; const b: MyStrictUnionType = ['foo', 'baz', 'bar']; // 顺序不影响 // 非法示例(均会报错) const c: MyStrictUnionType = ['foo', 'bar']; // 缺少'baz' const d: MyStrictUnionType = ['foo', 'foo', 'baz']; // 缺少'bar' const e: MyStrictUnionType = ['foo', 'boo', 'baz']; // 缺少'bar'且包含非法成员'boo'
本质是要在TypeScript中实现类似以下JavaScript逻辑的类型校验:
const myUnion = ["foo", "bar", "baz"]; const hasAllUnionMembers = (arr) => myUnion.every(unionMember => arr.includes(unionMember));
解决方案
可以通过类型条件判断和联合类型的分布式特性实现该类型:
type StrictArrayOfUnion<U> = T extends readonly any[] ? (U extends T[number] ? true : false) extends true ? T : never : never;
类型解析
- 首先,
T extends readonly any[]确保我们处理的是数组类型,同时数组元素会自动被约束为U的成员(只有合法数组会被返回); - 核心校验逻辑
U extends T[number] ? true : false:利用联合类型的分布式特性,把U拆成单个成员逐一检查——每个成员是否存在于数组元素的联合类型T[number]中。所有成员都存在时结果为true,否则为false; - 最后,校验通过时返回原数组类型
T,否则返回never触发类型报错。
内容的提问来源于stack exchange,提问作者JD Francis
相关产品推荐
相关产品推荐

