如何在TypeScript类型中替换包含特定字符串的键?
TypeScript类型键的子串替换实现问题
需求:实现TypeScript类型转换,当对象类型的键包含替换类型中的键时,将键内的对应子串替换为替换类型的对应值(每个键仅含一处待替换内容)。
当前可行的完全匹配实现
以下代码仅能处理键与替换类型键完全相等的情况:
type Replacements = { abc: 'cba'; bcd: 'dcb'; }; type Test = { bcd: string; aabca: string; }; type ReplaceKeys<R extends Record<string, string>, T extends Record<string, unknown>> = { [K in keyof T as K extends keyof R ? R[K] : K]: T[K]; }; type Replaced = ReplaceKeys<Replacements, Test>; // 结果: // type Replaced = { // dcb: string; // aabca: string; // }
尝试的子串替换实现(失败)
尝试了两种写法,均无法实现包含子串的替换:
写法一
type ReplaceKeysInferred< R extends Record<string, string>, T extends Record<string, unknown>, > = { [K in keyof T as K extends `${infer A}${infer RKey extends keyof R & string}${infer B}` ? `${A}${R[RKey]}${B}` : K]: T[K]; }; type ReplacedInferred = ReplaceKeysInferred<Replacements, Test>; // 结果未替换: // type ReplacedInferred = { // bcd: string; // aabca: string; // }
写法二
type ReplaceKeysInferred< R extends Record<string, string>, T extends Record<string, unknown>, > = { [K in keyof T as K extends `${infer A}${infer RKey}${infer B}` ? RKey extends keyof R ? `${A}${R[RKey]}${B}` : K : K]: T[K]; }; type ReplacedInferred = ReplaceKeysInferred<Replacements, Test>; // 结果仍未替换: // type ReplacedInferred = { // bcd: string; // aabca: string; // }
问题原因
TypeScript在映射类型的as子句中直接使用模式匹配时,不会自动枚举替换类型R的所有键去尝试匹配目标键K的子串,而是将RKey视为一个整体类型,无法触发对keyof R联合类型的遍历匹配。
解决方案
通过提取辅助类型单独处理单个键的子串替换,让TypeScript能够枚举R的键来尝试匹配:
// 辅助类型:处理单个字符串键的子串替换 type ReplaceSingle<K extends string, R extends Record<string, string>> = K extends `${infer A}${infer Key extends keyof R & string}${infer B}` ? `${A}${R[Key]}${B}` : K; // 主类型:遍历对象的所有键,应用替换逻辑 type ReplaceKeys<R extends Record<string, string>, T extends Record<string, unknown>> = { [K in keyof T as ReplaceSingle<K & string, R>]: T[K]; }; // 测试用例 type Replacements = { abc: 'cba'; bcd: 'dcb'; }; type Test = { bcd: string; aabca: string; xyzabcxyz: number; }; type Replaced = ReplaceKeys<Replacements, Test>; // 预期结果: // type Replaced = { // dcb: string; // aacba: string; // xyzcbaxyz: number; // }
原理说明
ReplaceSingle辅助类型接收单个字符串键K和替换类型R,通过模式匹配尝试匹配K中是否包含R的任意键作为子串。- 由于
Key extends keyof R & string的约束,TypeScript会自动枚举R的所有键逐一尝试匹配模式,匹配成功后替换对应子串。 - 主类型中通过
K & string确保键为字符串类型(兼容keyof T可能包含的number/symbol类型),然后对每个键应用ReplaceSingle完成替换。
内容的提问来源于stack exchange,提问作者Seb Heron
相关产品推荐
相关产品推荐

