如何实现TypeScript类型UniqueK<T>,校验类型中k字段值的唯一性?
TypeScript类型工具:检查字段
k值的唯一性 需求概述
- 给定一组类型(如元组、联合类型),检查每个类型的字段
k是否具有唯一值 - 实现类型
UniqueK<T>,判断T中是否存在至少两个类型的k值重复;若存在非字面量数字类型(如number、any、7|8),理想返回false(该要求非强制)
预期行为示例:
type UniqueK<T extends ...> = ... ? true : false; // 预期结果 UniqueK<[{k:1}, {k:2}]> = true UniqueK<[{k:7}, {k:42}, {k:0}]> = true UniqueK<[{k:1}, {k:1}]> = false // k:1重复 UniqueK<[{k:7}, {k:42}, {k:7}]> = false // k:7重复 UniqueK<[{k:number}, {k:1}]> = false // 包含非字面量数字类型
实现方案
核心思路
- 提取集合中所有元素的
k字段类型,组成联合类型 - 验证所有
k类型均为字面量数字 - 比较原集合的元素数量与
k联合类型的元素数量:若相等则无重复,否则存在重复
完整类型代码
// 提取集合中所有元素的k字段类型 type ExtractK<T> = T extends { k: infer K } ? K : never; // 判断是否为字面量数字类型 type IsLiteralNumber<T> = T extends number ? (number extends T ? false : true) : false; // 计算联合类型的元素个数 type UnionLength<T, Acc extends unknown[] = []> = T extends never ? Acc['length'] : UnionLength<Exclude<T, T>, [...Acc, unknown]>; // 核心类型:检查k值唯一性 type UniqueK<T extends readonly { k: number }[]> = ExtractK<T[number]> extends infer K ? (IsLiteralNumber<K> extends false ? false : (T['length'] extends UnionLength<K> ? true : false)) : false;
测试用例验证
type Test1 = UniqueK<[{k:1}, {k:2}]>; // true type Test2 = UniqueK<[{k:7}, {k:42}, {k:0}]>; // true type Test3 = UniqueK<[{k:1}, {k:1}]>; // false type Test4 = UniqueK<[{k:7}, {k:42}, {k:7}]>; // false type Test5 = UniqueK<[{k:number}, {k:1}]>; // false type Test6 = UniqueK<[{k:7|8}, {k:9}]>; // false
代码说明
ExtractK:通过条件类型推断,提取所有元素的k字段类型,最终得到这些类型的联合集合IsLiteralNumber:区分字面量数字(如1)和非字面量数字类型(如number、7|8):若number可以赋值给T,说明T是宽泛的数字类型,返回falseUnionLength:利用递归和Exclude操作,逐个移除联合类型的元素,通过累加数组长度来计算联合类型的元素数量UniqueK:先验证所有k都是字面量数字,再比较原元组的长度与k联合类型的长度——长度相等意味着没有重复的k值,返回true;否则返回false
内容的提问来源于stack exchange,提问作者Blue Nebula
相关产品推荐
相关产品推荐

