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

如何递归创建TypeScript类型对象,返回嵌套键路径字符串

实现支持嵌套属性路径的类型安全字段生成工具

在Angular项目中使用第三方表格组件时,组件的field属性接收字符串值,而表格行类型由Swagger Codegen自动生成,导致字段名无法获得类型校验。原方案通过Proxy生成与类型结构一致的对象,返回属性键名作为字符串,但仅支持平级属性,无法处理嵌套结构的完整路径(如subrow.firstSubrowColumn无法返回"subrow.firstSubrowColumn")。

下面给出递归实现的完整方案:

递归类型定义

修改类型系统,支持递归生成嵌套结构的类型约束:

// 提取非null/undefined的键
type NonNullableKeys<T> = {
  [K in keyof T]: T[K] extends null | undefined ? never : K;
}[keyof T];

// 递归生成属性路径类型:如果是对象(非数组、非基本类型)则递归,否则为字符串类型
type PropertiesOf<T> = {
  [K in NonNullableKeys<T>]: 
    T[K] extends Record<string, any> 
      ? T[K] extends any[] 
        ? string // 数组类型直接返回字符串(字段路径为数组属性名本身)
        : PropertiesOf<T[K]>
      : string;
};

递归Proxy实现

实现递归的getTypeProperties函数,通过Proxy的get陷阱递归创建子Proxy,并拼接父路径与当前属性名:

export function getTypeProperties<T>(parentPath = ''): PropertiesOf<T> {
  return new Proxy({}, {
    get: (_target, prop: string) => {
      // 拼接完整路径:如果有父路径则用点连接,否则直接用当前属性名
      const fullPath = parentPath ? `${parentPath}.${prop}` : prop;

      // 延迟创建子Proxy,访问子属性时自动拼接路径
      return getTypeProperties<any>(fullPath);
    }
  }) as PropertiesOf<T>;
}

使用示例

1. 定义行类型

type myTableValuesRowType = {
  firstColumn: number;
  secondColumn: string;
  thirdColumn: number[];
  fourthColumn: boolean;
  subrow: {
    firstSubrowColumn: string;
    secondSubrowColumn: number;
    nestedSubrow: {
      deepColumn: boolean;
    }
  }
}

2. 在组件中生成属性路径对象

// component.ts
readonly rowProperties = getTypeProperties<myTableValuesRowType>();

3. 在模板中使用

<my-table [values]="myTableValues">
  <my-column [field]="rowProperties.firstColumn" />
  <my-column [field]="rowProperties.subrow.firstSubrowColumn" />
  <my-column [field]="rowProperties.subrow.nestedSubrow.deepColumn" />
</my-table>

4. 验证结果

console.log(rowProperties.firstColumn); // 输出 "firstColumn"
console.log(rowProperties.subrow.firstSubrowColumn); // 输出 "subrow.firstSubrowColumn"
console.log(rowProperties.subrow.nestedSubrow.deepColumn); // 输出 "subrow.nestedSubrow.deepColumn"
console.log(rowProperties.thirdColumn); // 输出 "thirdColumn"

关键说明

  • 类型安全:TypeScript会严格校验属性访问,不存在的属性会直接报类型错误,避免拼写错误。
  • 递归拼接路径:通过传递父路径参数,每次访问子属性时自动拼接完整路径字符串。
  • 数组处理:数组类型直接返回属性名本身,符合表格组件通常的字段路径规则(不需要索引,直接用数组属性名)。
  • 无侵入:无需修改第三方UI组件库,完全通过类型工具和Proxy实现解耦。

内容的提问来源于stack exchange,提问作者T. Jami

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 04:08:12