☰
TypeScript 7 修复合成属性的 Setter 访问性:Union 与 Intersection 中的读写权限边界
2026/9/25 4:07:20 网站建设 项目流程
  • 文档
  • 教程

【免费下载链接】typescript-book

The Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.

项目地址:https://gitcode.com/gh_mirrors/typ/typescript-book
点击查看免费下载

导读:TypeScript 7 的原生(Go)检查器在 2026 年 8 月合并了一项针对合成属性的修复,从此对由 union(联合)与 intersection(交叉)类型合成的对象属性,读取(getter)与写入(setter)的访问权限将分别独立检查,不再混用。读完本文,你将理解该缺陷的触发场景、修复原理、验证方法,以及它在"公开读取、受限写入"这类封装设计中的实际意义。

背景:TypeScript 7 原生检查器与访问控制

TypeScript 7.0 是首个基于全新 Go 原生代码库构建的稳定版本(详见本站 TypeScript 7.0 发布公告),其编译器与语言服务都迁移到了原生实现上。随着检查器底层被重写,一些边角语义需要在原生代码中重新对齐——本文所述的 setter 访问性修复,正是这一迁移过程中被发现的语义偏差之一。

访问控制是 TypeScript 类设计的基础能力。本书 Class 章节中定义了三种访问修饰符:

  • public:无限制访问,可在任何地方读取或写入;
  • protected:仅允许在类内部及其派生类中访问;
  • private:仅允许在声明该成员的类内部访问。

当访问修饰符与 getter/setter 结合时,TypeScript 允许为读取和写入分别声明不同的可见性——这正是本次修复涉及的核心场景。而在 union / intersection 类型层面,对象类型被"合成"成新的属性视图,合成过程中访问性如何传递,就是本次缺陷所在。

问题本质:合成属性把 Setter 访问性错当成 Getter

当 TypeScript 将多个对象类型组合为 union(A | B)或 intersection(A & B)时,会为结果类型**合成(synthesize)**出对应的属性成员。在修复之前,检查器对这类合成属性的访问性检查存在一个偏差:写入访问性在实践上被读取访问性所覆盖。

具体表现为:如果一个类声明了public get foo与protected set foo,那么经由 union 或 intersection 访问该属性时,写入权限可能被错误地放宽为 public——因为检查器在判断时实际采用了 getter 的访问性,而忽略了 setter 自身的protected限制。

换言之,修复前存在一条"权限绕过"路径:类型系统层面本应拦截的非法写入,可以通过 union/intersection 的合成属性蒙混过关。

完整复现示例与逐行解读

原文档给出了如下最小复现,我们逐行展开分析:

declare class C1 { get foo(): number; protected set foo(value: number); } declare class C2 { get foo(): number; protected set foo(value: number); } declare const c: C1 | C2; c.foo; // Valid: read access is public c.foo = 123; // Invalid: write access is protected
  • declare class C1/C2:两个仅用于类型声明(无运行时实现)的类,二者拥有相同的属性签名——getter为 public,setter为 protected;
  • declare const c: C1 | C2:将两个类组合为联合类型。按 union 属性合并规则,foo成为由两方成员合成的联合属性;
  • c.foo:读取操作。getter 是 public,读取合法,类型为number;
  • c.foo = 123:写入操作。setter 是 protected,从模块外部写入本应报访问性错误。

修复前,第二行的写入可能不会触发错误——检查器沿用了 getter 的 public 访问性,导致受保护的 setter 限制形同虚设。修复后,检查器分别记录读写访问性:读取foo仍然合法,而赋值则会正确报告类似Property 'foo' is protected and only accessible within class 'C1' and its subclasses的访问性错误。

需要说明的是,文档中的修复同样适用于intersection类型(如C1 & C2)合成的属性;union 与 intersection 都会走属性合成路径,只是合并规则不同。

修复原理:getDeclarationModifierFlagsFromSymbolEx的修正

本次修复对应 TypeScript 官方合入的 pull request"FixgetDeclarationModifierFlagsFromSymbolExfor synthetic properties"(PR #63932),修复点位于原生检查器中负责提取"声明修饰符标志位"的内部函数。

从函数名可以推断其职责:getDeclarationModifierFlagsFromSymbolEx用于从符号(Symbol)上提取与声明位置相关的修饰符标志(如public、protected、private、readonly等)。在合成属性的场景下,getter 与 setter 是同一属性的两个不同声明部分,各自携带独立的访问修饰符;修复前该函数在合成属性上给出的标志位不足以区分"读取可见性"与"写入可见性",检查器因此退化为只使用 getter 的可见性做判断。修复的核心,就是让标志位提取逻辑对合成属性保留 getter 与 setter 各自的访问性信息,使读写检查各归其位。

从源码结构看,这一修复发生在原生编译器(tsgo/native codebase)的检查器路径上,而非旧的 JavaScript 实现,属于 TypeScript 7 原生迁移过程中的语义对齐修正之一。

为什么重要:守住"公开读取、受限写入"的封装边界

该修复的价值在于保护一种常见的封装设计模式——类刻意对外公开只读视图,同时限制写入路径。例如:

class BankAccount { private _balance: number = 0; get balance(): number { return this._balance; } protected set balance(value: number) { // 余额只能由类内部逻辑修改 this._balance = value; } }

这种"getter 公开、setter 受限"的组合,是只读属性、受控状态变更等设计的直接表达。TypeScript 在对象类型层面提供 union / intersection 组合能力(参见本书 Union Type 与 Intersection Types 章节),而组合过程中若意外放宽写入权限,就会击穿类自身声明的访问边界——让外部代码绕过类设计者的意图进行写入。本次修复确保:无论属性是原生声明还是由 union/intersection 合成,读写访问性都严格按各自声明执行,类型系统对封装边界的承诺在组合场景下依然成立。

对库作者而言,这意味着:只要在类内部坚持"getter/setter 分开声明访问修饰符",即便消费者将你的类与其他类型组合成 union 或 intersection,受保护的写入路径也不会被意外暴露。

如何在你的项目中验证

要验证当前安装的 TypeScript 是否包含该行为,可以按以下步骤操作:

  1. 检查已安装版本:npx tsc --version(TypeScript 7 系列请以安装的实际版本为准);
  2. 将上述复现代码保存为setter-accessibility.ts(注意保持getter与setter的访问修饰符一致声明);
  3. 执行npx tsc --noEmit setter-accessibility.ts,观察c.foo = 123一行是否报告访问性错误;
  4. 阅读对应版本的发行说明(release notes),确认是否包含"setter accessibility / synthetic properties"相关的修复条目。

注意:根据原文档说明,该变更在TypeScript 7.0 之后合入原生代码库,但来源并未指明包含它的稳定 npm 版本号。因此在依赖此行为之前,务必核对已安装版本的发行说明,不要假设所有 7.x 版本都已包含该修复。

可用性与来源

  • 发布时间:2026 年 8 月 24 日;
  • 状态:已合入 TypeScript 原生代码库;
  • 适用范围:由 union 与 intersection 合成属性的读写访问性检查;
  • 相关文档:本仓库的英文版 typescript-7-fixes-setter-accessibility.md,以及汇总了同期动态的 TypeScript News 索引页;
  • 官方来源:TypeScript 合入的 pull request ——FixgetDeclarationModifierFlagsFromSymbolExfor synthetic properties。

结合本书的 Class 章节中关于访问修饰符、getter/setter 与封装边界的完整讲解,可以系统性地掌握类成员可见性的完整语义,以及本次修复在组合类型场景下补上的最后一块拼图。

  • 文档
  • 教程

【免费下载链接】typescript-book

The Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.

项目地址:https://gitcode.com/gh_mirrors/typ/typescript-book
点击查看免费下载

相关推荐

上一篇:3大突破!让个人投资者也能掌握专业级缠论分析
下一篇:5分钟快速上手:PersonaLive实时人像动画终极指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询