TypeScript如何实现将对象所有键拼接为指定分隔符的联合类型?
TypeScript如何实现将对象所有键拼接为指定分隔符的联合类型?
嘿,这个需求其实可以通过TypeScript的条件类型和字符串模板类型来实现,咱们一步步来拆解~
首先看你的基础场景:对象只有两个键的情况,其实可以用嵌套的映射类型快速实现:
type MyObject = { one: string; two: string; }; // 针对两个键的精简版本 type Concatenator<T extends Record<string, string>, S extends string = '/'> = { [K1 in keyof T]: { [K2 in Exclude<keyof T, K1>]: `${K1}${S}${K2}` }[Exclude<keyof T, K1>] }[keyof T]; // 测试完全符合你的要求 const concatenated1: Concatenator<MyObject> = 'one/two'; // 合法 const concatenated2: Concatenator<MyObject> = 'two/one'; // 合法 // 输入不符合的字符串会直接报错,比如'one/one'或者'three/four'
这个思路特别直接:先遍历第一个键K1,再遍历排除K1后的剩余键K2,把它们用指定分隔符拼接起来,最后取所有可能结果的联合类型,刚好覆盖两种排列顺序。
但如果你的对象可能有更多键(比如3个、4个),上面的写法就不够通用了,这时候咱们可以写一个能处理任意数量字符串键的通用版本:
// 辅助类型:计算联合类型的元素个数 type LengthOfUnion<T> = T extends never ? 0 : (T extends infer U ? (U extends T ? 1 + LengthOfUnion<Exclude<T, U>> : 0) : 0); // 辅助类型:将字符串数组用分隔符拼接成单个字符串 type JoinKeys<Keys extends string[], Separator extends string> = Keys extends [infer First extends string, ...infer Rest extends string[]] ? Rest extends [] ? First : `${First}${Separator}${JoinKeys<Rest, Separator>}` : never; // 辅助类型:生成所有键的排列组合并拼接 type PermuteAndJoin<T extends string, Separator extends string, Accumulated extends string[] = []> = // 当积累的键数量等于原联合类型长度时,拼接成结果 LengthOfUnion<T> extends [...Accumulated, string]['length'] ? JoinKeys<Accumulated, Separator> : // 否则递归遍历剩余的键,生成所有排列 T extends infer U ? U extends string ? PermuteAndJoin<Exclude<T, U>, Separator, [...Accumulated, U]> : never : never; // 最终的通用Concatenator类型 type Concatenator<T extends Record<string, string>, S extends string = '/'> = PermuteAndJoin<keyof T & string, S>; // 测试多键场景 type MyObject3 = {a: string; b: string; c: string}; const concatenated3: Concatenator<MyObject3> = 'a/b/c'; // 合法 const concatenated4: Concatenator<MyObject3> = 'b/c/a'; // 合法 const concatenated5: Concatenator<MyObject3> = 'c/a/b'; // 合法 // 不符合全键排列的字符串会报错
这个通用版本的核心逻辑是:
- 先通过
LengthOfUnion计算对象键的总数量,用来判断是否已经收集完所有键 JoinKeys递归把排列好的键数组用分隔符拼接成字符串PermuteAndJoin递归遍历所有可能的键排列,当收集到所有键时,就生成对应的拼接字符串,最终所有结果组成联合类型
这样不管你的对象有多少个字符串键,都能生成所有可能的键排列拼接结果,而且分隔符支持自定义(默认是/,你也可以改成-、_这类符号)。
备注:内容来源于stack exchange,提问作者MGX
相关产品推荐
相关产品推荐

