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

TypeScript中循环引用类型的无深度限制惰性求值点表示法路径校验与智能提示实现问询

TypeScript中循环引用类型的无深度限制惰性求值点表示法路径校验与智能提示实现问询

我现在在实现一个点表示法路径的类型校验工具,但遇到了两个核心的棘手问题,想请教大家有没有更好的解决方案。

先说说我的类型基础定义,这里有两个循环引用的类型:

type Message = { content: string; owner: Owner; };
type Owner = { email: string; ownedMessages: Message[]; };

需求说明

我要实现的路径校验工具,需要满足以下的有效/无效路径规则:

有效路径示例

  • "messages"
  • "messages.content"
  • "messages.owner"
  • "messages.owner.email"
  • "messages.owner.ownedMessages"
  • "messages.owner.ownedMessages.content"
  • 理论上支持无限嵌套,比如messages.owner.ownedMessages.owner.ownedMessages...这种层级可以无限延伸的路径

无效路径示例

  • 拼写错误的路径,比如messages.emaill、messages.foo、messages.ownerr
  • 指向不存在属性的路径,比如messages.owner.foo

核心约束

我有两个特别在意的约束条件,希望实现的方案能满足:

  1. 无深度限制:优先支持无限层级的路径嵌套,实在没办法才考虑加深度限制
  2. 惰性智能提示:希望TypeScript的智能提示是“懒加载”的:
    • 当用户输入messages.时,只提示content和owner两个属性
    • 当用户输入messages.owner.时,只提示email和ownedMessages两个属性
    • 而不是一开始就把所有可能的深层嵌套路径都列出来,避免智能提示过于杂乱

我目前的实现方案(存在缺陷)

我自己尝试写了一个方案,但它有两个明显的问题:有深度限制,而且是提前计算所有可能路径的(非惰性)。下面是我的实现代码:

type Message = { content: string; owner: Owner; };
type Owner = { email: string; ownedMessages: Message[]; };

// 问题1:必须依赖这个数组来指定最大深度
type Prev = [never, 0, 1, 2, 3, 4, 5];

type DotNotationPaths<T, MaxDepth extends number = 5> = 
  MaxDepth extends 0 ? never : 
  T extends object ? 
    { 
      [K in keyof T & string]: 
        T[K] extends Array<infer U> 
          ? K | `${K}.${DotNotationPaths<U, Prev[MaxDepth]>}` 
          : T[K] extends object 
            ? K | `${K}.${DotNotationPaths<T[K], Prev[MaxDepth]>}` 
            : K;
    }[keyof T & string] 
  : never;

type ValidMessagePath = "messages" | `messages.${DotNotationPaths<Message>}`;

// 符合预期的有效路径测试
const validPath1: ValidMessagePath = "messages.content"; // ✓
const validPath2: ValidMessagePath = "messages.owner"; // ✓
const validPath3: ValidMessagePath = "messages.owner.email"; // ✓
const validPath4: ValidMessagePath = "messages.owner.ownedMessages"; // ✓
const validPath5: ValidMessagePath = "messages.owner.ownedMessages.content"; // ✓
const validPath6: ValidMessagePath = "messages.owner.ownedMessages.owner.email"; // ✓
const validPath7: ValidMessagePath = "messages"; // ✓

// 符合预期的无效路径报错
// @ts-expect-error
const invalidPath1: ValidMessagePath = "messages.contentt"; // ✗
// @ts-expect-error
const invalidPath2: ValidMessagePath = "messages.owner.emailll"; // ✗
// @ts-expect-error
const invalidPath3: ValidMessagePath = "messages.ownerr"; // ✗

这个方案的缺陷很明显:

  • 必须通过Prev数组和MaxDepth参数限制最大嵌套深度,没办法支持真正的无限层级
  • 它会提前计算所有可能的嵌套路径,导致智能提示一开始就把所有层级的属性都列出来,完全不符合我想要的“惰性提示”需求

我了解到ArkType这类工具似乎能实现这种惰性的无限嵌套路径提示,但不知道具体是怎么用TypeScript类型系统实现的。想请教大家,有没有办法实现满足我这两个核心约束的路径校验工具?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 10:54:32