TypeScript中如何过滤联合类型内的反向重复二元组
解决方案
方案一:从生成逻辑避免反向重复(推荐)
直接调整配对生成逻辑,从根源上不会产生反向重复的配对,代码简洁且通用,支持任意长度的字符串字面量联合类型:
type Animal = "cat" | "dog" | "rabbit" // 辅助工具:提取联合类型的第一个成员 type TakeFirst<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; // 通用工具:生成联合类型所有无反向重复的两两配对 type UniquePairs<U extends string> = // 联合类型为空时终止递归 [U] extends [never] ? never : // 取出当前联合的第一个成员 TakeFirst<U> extends infer First extends string // 取出剩余的其他成员 ? Exclude<U, First> extends infer Rest extends string // 生成当前成员和所有剩余成员的配对,再递归生成剩余成员之间的配对 ? [First, Rest] | UniquePairs<Rest> : never : never; type Pairs = UniquePairs<Animal> // 最终类型:["cat", "dog"] | ["cat", "rabbit"] | ["dog", "rabbit"]
方案二:基于已有带重复的Pairs类型过滤
如果你需要保留原有生成逻辑,只对已经生成的带反向重复的Pairs类型做过滤,可以使用以下方案:
// 你的原有代码 type Animal = "cat" | "dog" | "rabbit" type PairsMap = { [K1 in Animal]: { [K2 in Animal]: K1 extends K2 ? never : [K1, K2] } } type Values<T> = T[keyof T] type Pairs = Values<Values<PairsMap>> // 过滤反向重复的工具类型 type FilterReversePairs<T extends [string, string]> = T extends [infer A, infer B] ? `${A}` extends `${B}` ? never : `${A}` extends `${infer AChar}${infer ARest}` ? `${B}` extends `${infer BChar}${infer BRest}` ? AChar extends BChar // 首字符相同则递归比较剩余字符 ? FilterReversePairs<[ARest, BRest]> extends never ? never : T // 首字符不同则只保留首字符字典序更靠前的配对 : `${AChar}${BChar}` extends `${BChar}${AChar}` ? never : `${AChar}` extends 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'|'k'|'l'|'m' ? BChar extends 'n'|'o'|'p'|'q'|'r'|'s'|'t'|'u'|'v'|'w'|'x'|'y'|'z' ? T : never : T : T : never; type UniquePairs = FilterReversePairs<Pairs> // 最终类型同样是["cat", "dog"] | ["cat", "rabbit"] | ["dog", "rabbit"]
内容的提问来源于stack exchange,提问作者yaforsh
相关产品推荐
相关产品推荐

