如何在TypeScript中定义带编译时重复检查的唯一数组类型?
实现编译时检查重复值的兼容Array接口类型
核心思路
通过TypeScript递归条件类型检测数组元素是否重复,同时定义构造函数类型,确保创建的数组在编译时无重复值,且返回的数组完全兼容原生Array接口。
完整实现代码
// 递归检测数组是否存在重复元素 type HasDuplicates<T extends readonly unknown[]> = T extends [infer First, ...infer Rest] ? First extends Rest[number] ? true : HasDuplicates<Rest> : false; // 如果数组有重复元素则返回never,触发编译报错 type UniqueArray<T extends readonly unknown[]> = HasDuplicates<T> extends true ? never : T; // 定义兼容Array接口的构造函数类型 interface UniqueConstructor { <T extends readonly unknown[]>(...args: UniqueArray<T>): T & Array<T[number]>; } // 实现构造函数 const Unique: UniqueConstructor = (...args) => args as any;
使用示例
合法场景(无重复值)
const arr = Unique('x', 'y', 'z'); // 可正常调用Array的所有原生方法 if (arr.includes('x')) { // 业务逻辑处理 }
非法场景(存在重复值)
// TypeScript编译器直接报错,提示参数类型不匹配 const arr = Unique('x', 'x', 'z'); if (arr.includes('x')) { // 业务逻辑处理 }
说明
HasDuplicates:递归遍历数组元素,判断当前元素是否存在于剩余元素中,存在则返回true,否则继续递归检查剩余数组。UniqueArray:若数组存在重复元素则返回never,导致函数参数类型不匹配,触发编译错误。UniqueConstructor:泛型函数约束输入参数为无重复数组,返回值同时保留原数组的字面量类型并兼容Array接口,确保可调用所有Array原生方法。
内容的提问来源于stack exchange,提问作者mehran
相关产品推荐
相关产品推荐

