TypeScript:如何用对象类型创建含唯一值且全覆盖的对象数组类型?
可以实现,具体方案如下
要让TypeScript严格限制数组必须包含myObj的所有值且无重复,核心是利用字面量类型、递归排列类型实现——普通数组类型无法直接做这类约束,需要借助元组的精确类型检查。
步骤1:锁定myObj的字面量类型
先给myObj加上as const断言,让TypeScript保留具体的字面量值,而非宽泛的string类型:
const myObj = { key1: "value1", key2: "value2" } as const;
步骤2:提取myObj的值类型
通过工具类型提取myObj所有值的联合类型:
type MyObjValues = typeof myObj[keyof typeof myObj]; // 得到 "value1" | "value2"
步骤3:定义生成全排列元组的工具类型
写一个递归类型,生成所有包含MyObjValues中所有元素的排列元组,每个元素是{commonKey: 具体值}的结构:
// 递归生成所有合法排列元组 type Permute<T extends string> = T extends never ? [] : { [K in T]: [{commonKey: K}, ...Permute<Exclude<T, K>>] }[T];
逻辑说明:每次从联合类型中选一个值作为元组的第一个元素,递归处理剩下的元素,直到所有值都被用完,确保每个值只出现一次且无遗漏。
步骤4:定义目标类型ArrayWithUniqueValues
把生成的排列元组联合起来,就是我们要的类型:
type ArrayWithUniqueValues = Permute<MyObjValues>;
测试验证
现在可以测试各种场景:
// ✅ 合法:包含所有值且无重复(两种排列都允许) const arr1: ArrayWithUniqueValues = [{commonKey: "value1"}, {commonKey: "value2"}]; const arr2: ArrayWithUniqueValues = [{commonKey: "value2"}, {commonKey: "value1"}]; // ❌ 非法:缺少一个值 const arr3: ArrayWithUniqueValues = [{commonKey: "value1"}]; // ❌ 非法:值重复 const arr4: ArrayWithUniqueValues = [{commonKey: "value1"}, {commonKey: "value1"}]; // ❌ 非法:使用了不在myObj中的值 const arr5: ArrayWithUniqueValues = [{commonKey: "value3"}, {commonKey: "value1"}];
注意事项
如果myObj的键值对数量超过TypeScript默认递归深度限制(50),这种方案会失效,但对于少量元素的场景完全适用。
内容的提问来源于stack exchange,提问作者Oleg
相关产品推荐
相关产品推荐

