You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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; }

解决方案

通过条件类型+递归映射实现核心逻辑,步骤如下:

  1. 优先判断当前类型是否为带pii: true的对象,若是则直接返回true;
  2. 若为普通对象(排除基本类型),则递归遍历其所有属性并应用ExtractPII;
  3. 非对象类型直接保留原类型。

实现代码:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 17:10:16