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

TypeScript 实现抽象类时仅删单个getter/setter为何无编译报错

TypeScript抽象类访问器实现校验规则说明

首先看你给出的示例代码:

abstract class P<T> {
  abstract method(): T;
  abstract get poke(): string;
  abstract set poke(p: string);
}

class C extends P<string> {
  _p: string = 'p';

  method() {
    return '5';
  }

  // 同时注释getter和setter会触发编译错误,但仅注释一个不会
  get poke(): string {
    return this._p;
  }

  set poke(p: string) {
    this._p = p;
  }
}

你观察到的“同时注释两者才报错”逻辑很直接:此时子类完全不存在poke这个成员,自然不满足抽象类的成员存在性要求,直接触发编译错误。而仅注释其中一个不报错的现象,是TypeScript的刻意设计,核心原因有以下几点:

  • 结构化类型系统的核心特性
    TypeScript采用结构化类型系统,而非名义类型系统。抽象类中同时声明get poke()和set poke(),本质是约定了poke是一个可读可写的string类型成员,它并不强制要求子类必须用访问器实现,也不强制要求必须同时有get和set:
    1. 你甚至可以直接用普通类属性实现public poke: string = 'p',完全可以通过校验,因为普通属性天然满足可读可写的要求。
    2. 仅注释掉get或者set时,子类仍然存在poke这个同名成员,只要该成员的读写类型和抽象类的约定兼容,就不会触发错误。
  • 兼容JavaScript原生语义
    JavaScript本身就支持仅定义getter或者仅定义setter的合法用法:
    1. 仅定义getter可以实现只读计算属性
    2. 仅定义setter可以实现只写属性(比如内部敏感数据不允许外部读取,仅允许写入做校验)
      如果TypeScript强制要求子类必须同时实现get和set,就会阻断这些合法的JS开发模式,不符合TypeScript“适配JS所有原生特性”的设计目标。
  • 向后兼容的历史包袱
    这种宽松的校验逻辑从TypeScript早期版本就已存在,大量存量代码已经依赖了这个特性。如果后续版本改成严格校验访问器的成对实现,会导致大面积的存量代码编译失败,因此官方一直没有调整这个规则。

如果业务场景需要强制要求子类必须同时实现get和set,可以通过自定义类型约束、或者代码审查规则来实现,TS默认没有提供对应的编译开关。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 02:36:03