TypeScript递归类型DeepReadonly<string>为何返回原string类型?
问题解答
你观察到的DeepReadonly<string>仍然是string类型的现象,本质是TypeScript对同态映射类型的内置特殊处理规则导致的,具体逻辑如下:
核心规则说明
你定义的DeepReadonly<T>属于TypeScript中的同态映射类型:只要映射类型的写法为{ [P in keyof T]: 类型逻辑 },就会被TS识别为同态映射,这类映射有两个核心特性:
- 会保留原类型的所有属性修饰符(比如原有属性的
readonly、可选标记?都会继承) - 作用于非纯对象类型时,会触发内置的短路返回逻辑
原始类型的短路逻辑
当同态映射类型作用于原始类型(string、number、boolean、symbol、null、undefined)、函数类型、正则表达式这类非纯对象类型时,TypeScript不会真的遍历keyof T生成新的对象类型,而是直接返回输入的原类型。
这个设计的核心原因是:上述类型本身就不存在可修改的自有属性,给它们加readonly修饰没有实际意义,TS做了自动优化。
你可以通过以下代码验证这个规则:
type MyReadonly<T> = { readonly [P in keyof T]: T[P] } type R1 = MyReadonly<number> // 结果为number type R2 = MyReadonly<() => void> // 结果为() => void type R3 = MyReadonly<{a: string}> // 结果为{readonly a: string}
递归终止的隐式出口
你定义的这个递归DeepReadonly不需要手动写基础终止条件,正是依赖这个短路逻辑:当递归到属性为原始类型/函数等类型时,会直接返回原类型,自动终止递归。
内容的提问来源于stack exchange,提问作者crazyones110
相关产品推荐
相关产品推荐

