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

为什么TypeScript中interface定义的readonly属性没有生效?

问题核心原因

你遇到的现象是TypeScript的正常设计,并未违反readonly的约束规则,核心原因有两点:

  • 类实现接口时,接口的readonly修饰符不会自动同步到实现类的属性上
  • 实例变量的类型声明用了无readonly约束的实现类Book,而非带约束的接口ReadExample

详细解释

  1. 接口readonly的作用范围
    接口的readonly仅约束该接口类型本身的属性读写规则,本质是约定“使用该接口类型访问属性时,该属性只能读不能写”,并不会强制要求实现它的类也把对应属性设为readonly。
    可写属性天然满足“可读”的契约要求,因此类实现接口时,完全可以把接口标记为readonly的属性定义为可写属性,这是符合TS类型规则的。你当前代码中Book类的book_id就是普通可写属性,因此操作Book类型的实例时,TS允许修改该属性。

  2. 变量类型声明的影响
    你当前的实例声明代码是let book: Book = new Book(2, 'Sis'),TS会按照Book类的类型定义做检查,而Book类的book_id没有readonly修饰,自然不会报错。
    如果你把变量类型指定为ReadExample:let book: ReadExample = new Book(2, 'Sis'),此时TS会按照ReadExample的规则做检查,再尝试修改book.book_id就会触发只读属性报错。


修复方案

方案1:给实现类的对应属性加readonly修饰

如果要求所有Book类实例的book_id都不可修改,直接给类属性加readonly修饰即可:

interface ReadExample {
    readonly book_id: number,
    book_name: string
}

class Book implements ReadExample{
    readonly book_id= 3; // 新增readonly修饰
    book_name = 'A Thousand Stars';
    constructor(book_id:number, book_name:string){
        this.book_id = book_id;
        this.book_name = book_name;
    }
}
let book: Book = new Book(2, 'Sis');
book.book_id = 3; // 此处TS会抛出只读属性不可修改的报错

方案2:声明实例时指定类型为带readonly约束的接口

如果不需要限制所有Book类实例的book_id只读,只需要当前实例遵循ReadExample的约束,直接修改变量类型即可:

let book: ReadExample = new Book(2, 'Sis'); // 变量类型指定为ReadExample
book.book_id = 3; // 此处TS会抛出只读属性不可修改的报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 12:27:04