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

TypeScript 4.5.2强类型嵌套属性路径报错适配方案咨询

解决TypeScript 4.5.2中"类型实例化过深"的强类型属性路径问题

原代码用于通过点符号强类型引用深层嵌套属性路径,在TypeScript 4.2.4中运行正常,但升级到4.5.2后触发编译错误:Type instantiation is excessively deep and possibly infinite.ts(2589)。这是因为TS 4.5对递归类型的检测逻辑更严格,原递归深度控制方式触发了编译器的深度限制。

修改思路

  • 优化递归终止条件:当剩余深度为0时直接返回空字符串,避免不必要的类型推断
  • 简化数组类型处理:合并数组与普通对象的路径生成逻辑,减少分支复杂度
  • 调整深度控制方式:用更直接的数字递减替代原Prev数组的间接索引,降低编译器的递归推断负担

修改后的完整代码

type BigNumber = {}; // BigNumber实际定义
type Ignore<T> = Exclude<T, BigNumber>;
type Join<K, P> = K extends string | number 
  ? P extends string | number 
    ? `${K}${"" extends P ? "" : "."}${P}` 
    : never 
  : never;

// 辅助类型:实现数字减1,替代原Prev数组
type Prev<T extends number> = 
  T extends 1 ? 0 : 
  T extends 2 ? 1 : 
  T extends 3 ? 2 : 
  T extends 4 ? 3 : 
  T extends 5 ? 4 : 
  T extends 6 ? 5 : 
  T extends 7 ? 6 : 
  T extends 8 ? 7 : 
  T extends 9 ? 8 : 
  T extends 10 ? 9 : 
  T extends 11 ? 10 : 
  T extends 12 ? 11 : 
  T extends 13 ? 12 : 
  T extends 14 ? 13 : 
  T extends 15 ? 14 : 
  T extends 16 ? 15 : 
  T extends 17 ? 16 : 
  T extends 18 ? 17 : 
  T extends 19 ? 18 : 
  T extends 20 ? 19 : never;

// 调整深度控制,直接使用数字递减,最大深度默认设为10
type DottedPaths<T, D extends number = 10> = 
  // 深度耗尽时终止递归
  D extends 0 ? "" : (
    Ignore<T> extends never ? "" : (
      T extends Array<infer TChild> 
        ? DottedPaths<TChild, D> // 数组直接递归子元素类型
        : {
            [K in keyof T]-?: K extends string | number
              ? `${K}` | Join<K, DottedPaths<T[K], Prev[D]>>
              : never
          }[keyof T]
    )
  );

interface IModel {
    propertyName: string;
    traits: {
        propertyName: string;
        trait: {
            propertyName: string;
        }
    }[];
    marketplace: {
        propertyName: string;
        secondaryPropertyName: string;
        traits: {
            propertyName: string;
            trait: {
                propertyName: string;
            }
        }[];
    }
}

const nameof = <TObject extends object>(name: DottedPaths<TObject>): string => name as string;

// 测试用例
nameof<IModel>('traits.trait.propertyName'); // 合法
nameof<IModel>('propertyName'); // 合法
nameof<IModel>('marketplace.traits.trait.propertyName'); // 合法

关键修改点说明

  • 把原Prev数组替换为明确的数字减1类型Prev<T>,减少编译器对数组索引的递归解析
  • 在DottedPaths开头增加深度耗尽的终止条件D extends 0 ? "",提前终止递归
  • 简化数组类型的处理逻辑,数组直接递归子元素的路径生成,避免重复的条件判断

内容的提问来源于stack exchange,提问作者Cody Bouche

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:52:11