TypeScript将readonly类型赋值给非readonly类型无报错,是否为Bug?
这个行为是 TypeScript 的预期设计,并非 Bug,原因和对应说明如下:
核心原理
你遇到的是 TypeScript 类型系统的「可变性兼容性」设计,as const 给 x 推导的类型是 { readonly a: 42 },而 TS 默认允许只读属性的类型赋值给对应可变属性的同类型,这种设计是为了兼顾开发体验:只读只是对源引用的操作限制,不代表值本身全局不可变,跨引用的可变性跟踪会带来极高的性能开销,TS 做了权衡取舍。
两个疑问的解释
- 为什么
const y: A = x不报错?
因为{ readonly a: 42 }和{ a: number }是结构化兼容的,TS 没有对这种可变性反向兼容做强制限制,如果你希望这里抛出错误,只需要把A的属性标记为只读:
或者给 y 的类型加interface A { readonly a: number; }Readonly修饰:const y: Readonly<A> = x; - 为什么
b被推断为 42?
你把 x 赋值给 y 只是做了类型兼容的隐式转换,没有修改 x 本身的类型定义,x 的类型自始至终都是{ readonly a: 42 },所以 TS 对 x.a 的推断永远是字面量 42。
这里确实存在类型和运行时不一致的情况:因为 x 和 y 指向同一个引用,修改 y.a 之后运行时 x.a 实际值为 24,但 TS 的类型系统不会跟踪这种跨别名的修改行为,属于已知的设计边界。
Readonly 的实际意义
Readonly 修饰符的作用是约束当前引用的操作,而非标记值本身全局不可变。比如你直接执行 x.a = 24 时,TS 会直接抛出类型错误,这就是它的核心作用:避免你直接操作修改原本定义为只读的引用,降低误操作概率。
内容的提问来源于stack exchange,提问作者LGenzelis
相关产品推荐
相关产品推荐

