TypeScript泛型构建模板字面量时能否遍历嵌套对象?
实现TypeScript嵌套对象键的$select模板字面量
完全可以实现这个需求,通过组合TypeScript的泛型工具类型和递归模板字面量,就能生成符合要求的$select格式字符串类型。
核心实现步骤
- 提取值为对象类型的属性键:用
KeysWithValsOfType工具类型筛选出目标类型中值为对象的属性名。 - 生成逗号分隔的键组合:通过递归模板字面量,生成嵌套对象键的所有单个或多个逗号分隔的组合。
- 拼接最终模板字面量:将属性名与对应的$select组合拼接成完整的查询字符串类型。
完整代码示例
// 提取类型T中值为U类型的属性键 type KeysWithValsOfType<T, U> = { [K in keyof T]: T[K] extends U ? K : never; }[keyof T]; // 生成所有非空的逗号分隔键组合(支持单个或多个键) type CommaSeparated<T extends string | number | symbol> = T extends infer U extends string | number | symbol ? U | `${U},${CommaSeparated<Exclude<T, U>>}` : never; // 生成最终的查询字符串类型 type SelectQuery<T> = { [K in KeysWithValsOfType<T, object>]: `${K}($select=${CommaSeparated<keyof T[K]>})`; }[KeysWithValsOfType<T, object>];
测试用例
定义一个包含嵌套对象的类型:
type User = { id: number; name: string; person: { firstName: string; lastName: string; age: number; }; address: { street: string; city: string; }; };
使用SelectQuery<User>会生成以下类型联合(仅展示部分示例):
// 包含所有合法的组合,比如: "person($select=firstName)" | "person($select=firstName,lastName)" | "person($select=lastName,age)" | "address($select=street)" | "address($select=street,city)"
说明
CommaSeparated通过递归实现了所有可能的键组合,包括单个键和任意多个逗号分隔的键。- 最终的
SelectQuery会自动遍历所有值为对象的属性,为每个属性生成对应的$select格式字符串。 - 若嵌套对象的键数量较多,TypeScript可能触发递归深度限制,但常规业务场景下完全够用。
内容的提问来源于stack exchange,提问作者phmsk
相关产品推荐
相关产品推荐

