- 文档
- 教程
【免费下载链接】typescript-book
The Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.
导读: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 protecteddeclare 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 是否包含该行为,可以按以下步骤操作:
- 检查已安装版本:
npx tsc --version(TypeScript 7 系列请以安装的实际版本为准); - 将上述复现代码保存为
setter-accessibility.ts(注意保持getter与setter的访问修饰符一致声明); - 执行
npx tsc --noEmit setter-accessibility.ts,观察c.foo = 123一行是否报告访问性错误; - 阅读对应版本的发行说明(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 ——Fix
getDeclarationModifierFlagsFromSymbolExfor synthetic properties。
结合本书的 Class 章节中关于访问修饰符、getter/setter 与封装边界的完整讲解,可以系统性地掌握类成员可见性的完整语义,以及本次修复在组合类型场景下补上的最后一块拼图。
- 文档
- 教程
【免费下载链接】typescript-book
The Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.
相关推荐
TypeScript 7 修复 union/intersection 合成属性的 setter 可访问性检查:读写权限分离解析
TypeScript 7 修复 union/intersection 合成属性的 setter 可访问性检查:读写权限分离解析 本文基于 typescript
文档教程Managed Service for Apache Airflow DAG 排障指南:基于 gcloud 日志与源码的确定性故障定位实战
Managed Service for Apache Airflow DAG 排障指南:基于 gcloud 日志与源码的确定性故障定位实战 本指南完整讲解如何在
文档教程TypeScript 7 修复联合类型与交叉类型中 setter 可访问性:合成属性读写权限分离
TypeScript 7 修复联合类型与交叉类型中 setter 可访问性:合成属性读写权限分离 导读: TypeScript 7 的原生类型检查器合并了一项修
文档教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考