TypeScript如何基于条件递归替换嵌套对象的所有类型?
递归实现TypeScript的PII属性提取
问题描述
TypeScript官网《Further Exploration》中的ExtractPII类型仅能处理对象的第一层属性:将包含pii: true的属性标记为true,其余标记为false。但实际场景中需要递归遍历所有嵌套属性:只要某个嵌套对象存在pii: true,就将其替换为true;普通嵌套对象则继续深入处理内部属性,非对象类型保持原结构。
原单层处理示例:
type ExtractPII<Type> = { [Property in keyof Type]: Type[Property] extends { pii: true } ? true : false; }; type DBFields = { id: { format: "incrementing" }; name: { type: string; pii: true }; }; type ObjectsNeedingGDPRDeletion = ExtractPII<DBFields>; // 结果:{ id: false; name: true; }
我们需要实现的嵌套处理效果:
type DBFields = { id: { format: "incrementing", foo: { type: string; pii: true } }; name: { type: string; pii: true }; }; type ObjectsNeedingGDPRDeletion = ExtractPII<DBFields>; // 期望结果:{ id: { format: "incrementing"; foo: true }; name: true; }
解决方案
通过条件类型+递归映射实现核心逻辑,步骤如下:
- 优先判断当前类型是否为带
pii: true的对象,若是则直接返回true; - 若为普通对象(排除基本类型),则递归遍历其所有属性并应用
ExtractPII; - 非对象类型直接保留原类型。
实现代码:
type ExtractPII<T> = // 匹配带pii:true的对象,直接替换为true T extends { pii: true } ? true // 匹配普通对象,递归处理每个属性 : T extends object ? { [K in keyof T]: ExtractPII<T[K]> } // 非对象类型保留原类型 : T; // 测试用例 type DBFields = { id: { format: "incrementing", foo: { type: string; pii: true } }; name: { type: string; pii: true }; age: number; address: { street: string; city: { code: string; pii: true }; }; }; type ObjectsNeedingGDPRDeletion = ExtractPII<DBFields>; /** * 最终结果: * { * id: { format: "incrementing"; foo: true }; * name: true; * age: number; * address: { street: string; city: true }; * } */
扩展:支持数组类型
如果需要处理数组中的嵌套属性,可以在条件中增加数组判断分支:
type ExtractPII<T> = T extends { pii: true } ? true // 处理数组,递归处理数组元素类型 : T extends Array<infer U> ? ExtractPII<U>[] : T extends object ? { [K in keyof T]: ExtractPII<T[K]> } : T; // 数组测试用例 type DBArray = { records: { id: number; user: { name: string; pii: true } }[] }; type ProcessedArray = ExtractPII<DBArray>; // 结果:{ records: { id: number; user: true }[] }
内容的提问来源于stack exchange,提问作者fusio
相关产品推荐
相关产品推荐

