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

如何在TypeScript中指定方法不修改类,实现类的不可变引用?

作为习惯了C++const机制的开发者,你想要在TypeScript里实现类似的——区分只读/可变方法、创建不可变引用的效果对吧?虽然TypeScript没有直接对应C++const成员函数的语法,但我们可以用接口分离原则完美复刻这个逻辑,甚至更灵活。

实现类似C++的const机制在TypeScript里

1. 分离只读与可变接口

首先,把类里的“只读方法”(对应C++的const成员函数)抽成一个独立接口,让你的类实现这个接口,同时保留可变方法。这样就能明确区分哪些操作是允许在不可变实例上执行的:

// 只读接口:只包含不修改实例的方法
interface ReadonlyA {
  get(): number;
  // 其他只读方法也可以放在这里
}

// 可变类:实现只读接口,同时添加修改状态的方法
class A implements ReadonlyA {
  x: number;

  get(): number {
    return this.x;
  }

  set(x: number): void {
    this.x = x;
  }
}

2. 使用只读接口作为不可变引用

现在,当你需要“不可变引用”时,直接用ReadonlyA类型代替A,TypeScript会自动阻止你调用任何修改方法,和C++的const A&效果完全一致:

// 可变实例:拥有全部操作权限
const mutableA: A = new A();
mutableA.set(5); // 合法
console.log(mutableA.get()); // 输出 5

// 不可变引用:只能调用只读方法
const immutableA: ReadonlyA = mutableA;
immutableA.get(); // 合法
immutableA.set(10); // ❌ 报错:类型'ReadonlyA'上不存在属性'set'

你可以把可变实例赋值给不可变引用,但反过来不行——这和C++里const引用的规则完全匹配。

3. 进阶:避免重复代码(自动生成只读类型)

如果你的类方法很多,手动写只读接口太麻烦,可以用TypeScript的工具类型简化。比如定义一个通用的Immutable<T>类型,自动提取类中的只读方法(这里假设修改方法的命名有规律,或者你可以通过条件类型更精准地筛选):

// 通用Immutable类型:移除所有以set开头的方法,并把属性设为只读
type Immutable<T> = Readonly<T> & Omit<T, keyof { [K in keyof T]: T[K] extends (...args: any[]) => void ? K extends `set${string}` ? K : never : never }>;

// 使用示例
const immutableA: Immutable<A> = new A();
immutableA.get(); // 合法
immutableA.set(10); // ❌ 报错

不过手动分离接口还是最清晰的方案,就像C++里显式标记const方法一样,能明确传达代码意图。

4. 强制只读方法不修改实例

在C++里,const方法会强制编译器检查是否修改了成员变量,TypeScript里可以用readonly修饰属性来实现类似的约束:

class A implements ReadonlyA {
  readonly x: number = 0; // 标记属性为只读

  get(): number {
    this.x = 10; // ❌ 报错:无法分配到"x",因为它是只读属性
    return this.x;
  }

  // 注意:如果需要set方法修改属性,就不要用readonly修饰x,靠接口约束外部调用即可
  set(x: number): void {
    this.x = x;
  }
}

这里的取舍是:如果属性本身是只读的,用readonly强制内部也不能修改;如果类内部需要修改属性,就去掉readonly,靠接口约束外部调用者无法触发修改。

对比C++与TypeScript的实现

C++特性TypeScript对应实现
const成员函数只读接口中的方法
const A&不可变引用ReadonlyA类型变量
编译器检查const方法是否修改成员readonly属性+接口约束

这种方案完全满足你的需求:部分用户拿到可变实例可以修改状态,其他用户拿到不可变引用只能执行只读操作,和C++的体验几乎一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:40:11