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

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 的属性标记为只读:
    interface A {
      readonly a: number;
    }
    
    或者给 y 的类型加 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 07:48:00