如何基于嵌套对象与字符串字面量数组生成TypeScript复合类型
TypeScript复合类型生成解决方案:嵌套对象与指定键的拼接类型
需求描述
基于嵌套对象和字符串字面量数组生成复合类型,要求:
- 包含字面量数组中列出的键与其子键拼接后的结果(如
foo对应foo.a、foo.b) - 保留未在数组中的原对象键(如
bar)
示例代码:
const data = { foo: { a: 1, b: 'b', }, bar: { c: () => {} }, baz: { d: 'test', e: 42 }, }; const literals = ['foo', 'baz'] as const satisfies readonly (keyof typeof data)[]; /** 目标实现MagicFunction */ type magicOutput = MagicFunction<typeof data, typeof literals>; /** 期望输出类型 */ type expectedOutput = 'foo.a' | 'foo.b' | 'bar' | 'baz.d' | 'baz.e';
遇到的问题
已实现仅支持单个字符串字面量的SemiMagicFunction,但生成目标类型需硬编码数组条目,无法随literals数组变更自动更新。尝试使用Keys[number]时,Object[Keys[number]]始终返回never,需要可行的TypeScript解决方案。
解决方案
通过分布式条件类型和模板字面量类型实现自动生成目标类型,无需硬编码数组条目:
type MagicFunction<T extends Record<string, object>, K extends readonly (keyof T)[]> = // 保留未在字面量数组中的原对象键 Exclude<keyof T, K[number]> | // 处理字面量数组中的键,拼接其子键为联合类型 { [Key in K[number]]: `${Key & string}.${keyof T[Key] & string}` }[K[number]];
原理说明
Exclude<keyof T, K[number]>:筛选出原对象中不在字面量数组内的键,直接作为类型成员保留。- 分布式拼接逻辑:
- 遍历字面量数组中的每个键
Key,生成Key.SubKey格式的模板字面量类型 - 通过
[K[number]]索引访问实现分布式类型,将所有拼接结果合并为联合类型
- 遍历字面量数组中的每个键
验证测试
type magicOutput = MagicFunction<typeof data, typeof literals>; // 类型等价于:'foo.a' | 'foo.b' | 'bar' | 'baz.d' | 'baz.e'
内容的提问来源于stack exchange,提问作者petroni
相关产品推荐
相关产品推荐

