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

为何TypeScript中`T[keyof T] extends Function`可执行?递归类型无循环?

为什么DeepReadonly递归不会无限循环?

先看你的代码:

type DeepReadonly<T> = {
  readonly [k in keyof T]: T[k] extends Function ? T[k] : DeepReadonly<T[k]>
}

type X1 = {a: string};
type A = DeepReadonly<X1>

你疑惑的是当传入string类型到DeepReadonly时,为什么不会无限递归?核心原因有两个:

  • 基础类型的递归收敛:当T是string这类基础类型时,虽然keyof string会返回它的内置属性(比如toString、charAt,还有索引签名number),但在处理映射类型的属性值时:

    • 对于Function类型的属性(比如toString),条件判断会直接返回原函数类型,不会递归;
    • 对于索引签名number对应的string类型,虽然会触发DeepReadonly<string>,但TypeScript会识别到这是循环引用且不会产生新类型结构的情况——因为DeepReadonly<string>最终的结构和string本身完全兼容(基础类型没有可修改的属性,readonly修饰符对它无效),所以会直接终止递归,返回string类型。
  • TypeScript的惰性求值与递归优化:TypeScript对条件类型和递归类型采用惰性求值,只有在需要实际解析类型结构时才会展开。对于这种递归到基础类型的场景,TypeScript会判断继续展开不会得到新的信息,因此会停止递归,避免无限循环。

实际验证的话,你可以查看A的类型推断结果,它会是{ readonly a: string },完全符合预期,没有出现无限递归的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 09:41:32