尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
TypeScript 2.9 破坏性变更全解析:`keyof` 泛化、剩余参数语法与严格空检查下的类型约束变化
文档教程【免费下载链接】TypeScriptTypeScript 使用手册中文版翻译。http://www.typescriptlang.org项目地址https://gitcode.com/gh_mirrors/typ/TypeScript点击查看免费下载导读TypeScript 2.9 是本手册中一个重要的破坏性变更版本它把索引类型keyof从仅支持字符串键名泛化为同时支持number和symbol键名同时收紧了两处编译期行为剩余参数后面不允许尾后逗号、strictNullChecks下无类型约束参数不再可赋值给object。本文以 zh/breaking-changes/typescript-2.9.md 为主体结合本仓库 zh/release-notes/typescript-2.9.md 与 zh/handbook-v2/type-manipulation/keyof-type-operator.md 等文档系统讲解每一处变更的触发条件、报错样例、迁移建议与底层原理帮助你在升级到 2.9 后快速定位并修复存量代码。一、keyof现在包括string、number和symbol键名这是 TypeScript 2.9 最具影响力的破坏性变更。变更前keyof只认识字符串键在 2.9 之前keyof运算符和映射类型仅支持string命名的属性。也就是说对于一个对象类型keyof T产生的联合类型只能包含字符串字面量数字字面量键与唯一的symbol键都会被忽略。变更后keyof反映全部三种属性键2.9 起keyof T是string | number | symbol的子类型且解析规则细化如下摘自 zh/release-notes/typescript-2.9.md 第 13–23 行如果X带有字符串索引签名则keyof X为string、number和表示 symbol-like 属性的字面量类型的联合否则如果X带有数字索引签名则keyof X为number和表示 string-like、symbol-like 属性的字面量类型的联合否则keyof X为表示 string-like、number-like 和 symbol-like 属性的字面量类型的联合。其中属性的分类方式为string-like 属性使用标识符、字符串字面量或计算后值为字符串字面量类型的属性名所声明number-like 属性使用数字字面量或计算后值为数字字面量类型的属性名所声明symbol-like 属性使用计算后值为 symbol 字面量类型的属性名所声明。完整的综合示例来自发布说明const c c; const d 10; const e Symbol(); const enum E1 { A, B, C, } const enum E2 { A A, B B, C C, } type Foo { a: string; // String-like name 5: string; // Number-like name [c]: string; // String-like name [d]: string; // Number-like name [e]: string; // Symbol-like name [E1.A]: string; // Number-like name [E2.A]: string; // String-like name }; type K1 keyof Foo; // a | 5 | c | 10 | typeof e | E1.A | E2.A type K2 Extractkeyof Foo, string; // a | c | E2.A type K3 Extractkeyof Foo, number; // 5 | 10 | E1.A type K4 Extractkeyof Foo, symbol; // typeof e注意这里的分类依据是计算值字符串字面量c对应的键是 string-like数字字面量d对应的是 number-like而数字枚举成员E1.A因为计算值为数字被归为 number-like字符串枚举成员E2.A则被归为 string-like。映射类型同步泛化映射类型{ [P in K]: XXX }中的K现在允许是可以赋值给string | number | symbol的任何值。其行为发布说明第 25 行为K的每个字符串字面量类型都会引入一个名字为字符串的属性每个数字字面量类型都会引入一个名字为数字的属性每个 symbol 字面量类型都会引入一个名字为 symbol 的属性若K包含string类型则同时引入字符串索引类型若K包含number类型则同时引入数字索引类型。这一泛化带来一个直接收益PartialT、ReadonlyT等内建映射类型现在能正确保留并处理带数字索引签名的对象类型。例如发布说明第 61–74 行type ArrayishT { length: number; [x: number]: T; }; type ReadonlyArrayishT ReadonlyArrayishT; declare const map: ReadonlyArrayishstring; let n map.length; let x map[123]; // 2.9 之前为 any或在 --noImplicitAny 下报错新能力抽象访问数字枚举与唯一 symbol 键由于keyof支持number和symbol命名的键现在可以对数字字面量如数字枚举类型与唯一 symbol 属性的访问进行抽象。典型场景是枚举/ symbol 到值的映射表发布说明第 78–110 行const enum Enum { A, B, C, } const enumToStringMap { [Enum.A]: Name A, [Enum.B]: Name B, [Enum.C]: Name C, }; const sym1 Symbol(); const sym2 Symbol(); const sym3 Symbol(); const symbolToNumberMap { [sym1]: 1, [sym2]: 2, [sym3]: 3, }; type KE keyof typeof enumToStringMap; // Enum (即 Enum.A | Enum.B | Enum.C) type KS keyof typeof symbolToNumberMap; // typeof sym1 | typeof sym2 | typeof sym3 function getValueT, K extends keyof T(obj: T, key: K): T[K] { return obj[key]; } let x1 getValue(enumToStringMap, Enum.C); // 返回 Name C let x2 getValue(symbolToNumberMap, sym3); // 返回 3本仓库的 zh/handbook-v2/type-manipulation/keyof-type-operator.md 也提醒读者当类型带有string或number索引签名时keyof会返回相应类型对于带字符串索引签名的MapishM会是string | number因为 JavaScript 对象的键总是被强制转换为字符串obj[0]始终等同于obj[0]。而 zh/handbook-v2/type-manipulation/mapped-types.md 则展示了映射类型如何基于keyof产生的联合类型遍历键来构建新类型并可通过-readonly、-?等修饰符增删属性特性这些能力在 2.9 后都能覆盖到 number-like 与 symbol-like 属性。破坏性把keyof T当string的代码开始报错这是本变更最需要关注的破坏点。原先把keyof T直接当作string使用的代码在 2.9 下会产生编译错误function useKeyT, K extends keyof T(o: T, k: K) { var name: string k; // 错误: keyof T 不能分配给 string }因为keyof T现在可能包含number与symbol字面量不能再安全地赋给string。迁移建议一函数只处理字符串键时用Extractkeyof T, string收窄如果你的函数只能处理字符串命名属性的键请在声明中使用Extractkeyof T, string显式收窄类型参数约束function useKeyT, K extends Extractkeyof T, string(o: T, k: K) { var name: string k; // OK }Extractkeyof T, string会从keyof T中取出所有 string-like 的成员保证K始终可以赋给string。这与 zh/breaking-changes/typescript-2.9.md 中给出的修复方式完全一致也顺带对应了for...in迭代变量推断的变化针对泛型T的对象的for...in语句迭代变量的推断类型从keyof T改为Extractkeyof T, string即仅保留类字符串的值。迁移建议二函数能处理所有属性键时放宽变量类型如果你的函数可以处理任意类型的属性键把变量的类型放宽为string | number | symbol即可function useKeyT, K extends keyof T(o: T, k: K) { var name: string | number | symbol k; }迁移建议三使用--keyofStringsOnly关闭新行为如果短期内不想迁移存量代码可以继续使用--keyofStringsOnly编译器选项禁用新行为让keyof退化为只包含字符串键。该选项在后续版本中仍被保留本仓库 zh/release-notes/typescript-5.4.md 第 343 行仍提及keyofStringsOnly可视为一个兼容性逃生舱。二、剩余参数后面不允许尾后逗号变更内容自 TypeScript 2.9 起对应 GitHub PR #22262在剩余参数rest parameter后面写尾随逗号会被视为编译器错误。以下代码即为违规示例function f(a: number, ...b: number[]) { // 违规的尾随逗号 }原因与影响尾随逗号放在剩余参数之后不是有效的 JavaScript。在 ES2015 的 rest 参数语法中剩余参数必须位于参数列表的末尾其后不能再有任何逗号或参数。2.9 之前 TypeScript 允许这种写法属于对非法语法的宽松处理2.9 起编译器将其收紧为错误与标准 JavaScript 保持一致。对迁移者的启示排查所有形如function f(...args: T[],)的函数声明、函数类型表达式与调用处删除剩余参数后面的逗号注意普通参数列表如function f(a: number, b: number,)中的尾随逗号不受影响它依然是合法的本变更只针对剩余参数之后的尾随逗号。三、strictNullChecks下无类型约束参数不再可赋值给object变更内容在开启strictNullChecks时无类型约束unconstrained的泛型参数不再允许赋值给object类型。以下代码自 GitHub issue #24013 起成为编译错误function fT(x: T) { const y: object | null | undefined x; }--strictNullChecks的作用可参见本仓库 zh/project-config/compiler-options.md 第 80 行的说明在严格的 null 检查模式下null和undefined值不包含在任何类型里只允许用它们自己和any来赋值。而T没有约束意味着它可以用任意类型实例化——例如string、number、boolean甚至null与undefined本身——因此把它当作object | null | undefined接收是不正确的2.9 起编译器禁止了这一不安全的赋值。迁移建议只想接受对象类型给类型参数加上object约束强制T必须是对象类型function fT extends object(x: T) { const y: object | null | undefined x; // OKT 被限制为对象 }想允许任意类型改用{}进行比较或赋值而不是object。{}代表非null/undefined的任意值覆盖面比object更广function fT(x: T) { const y: {} | null | undefined x; // OKT 可为任意非空值 }一句话总结object严格表示对象这一大类{}表示除null/undefined外的任意值两者在泛型约束场景下语义差别很大选择时务必结合函数实际允许的实参范围。四、变更之间的关联与升级检查清单上述三处变更虽各自独立但都服务于同一个方向让类型系统更精确、更贴近 JavaScript 运行时真实语义。keyof泛化让索引类型真实反映对象可能拥有的全部键种类剩余参数尾随逗号报错让语法检查对齐标准无约束泛型不可赋给object则堵住了严格空检查下的类型漏洞。升级到 TypeScript 2.9 时建议按以下清单自查全库搜索keyof T直接赋给string的代码改用Extractkeyof T, string或放宽变量类型检查for...in迭代泛型对象时对迭代变量类型的假设现推断为Extractkeyof T, string搜索函数声明中...args之后是否残留尾随逗号并删除在strictNullChecks下检查无约束泛型参数是否被赋给object类型按需添加extends object约束或改用{}若存量代码过多、迁移周期紧张可临时开启--keyofStringsOnly恢复旧行为可配置于命令行或 tsconfig.json 的compilerOptions中。参考与延伸阅读破坏性变更主体文档zh/breaking-changes/typescript-2.9.md同版本发布说明含完整示例与更多 2.9 新特性如import类型、import.meta、--resolveJsonModule、--declarationMap等zh/release-notes/typescript-2.9.mdkeyof类型运算符详解zh/handbook-v2/type-manipulation/keyof-type-operator.md映射类型与keyof的组合用法zh/handbook-v2/type-manipulation/mapped-types.md泛型约束与keyof的经典用法getPropertyT, K extends keyof Tzh/handbook/generics.md编译器选项总表--strictNullChecks、--pretty等zh/project-config/compiler-options.mdtsconfig.json配置写法zh/project-config/tsconfig.json.md赞分享文档教程【免费下载链接】TypeScriptTypeScript 使用手册中文版翻译。http://www.typescriptlang.org项目地址https://gitcode.com/gh_mirrors/typ/TypeScript点击查看免费下载相关推荐Slang 泛型完全指南从语法、类型检查到参数绑定与 Pack 约束的实践解析Slang 泛型完全指南从语法、类型检查到参数绑定与 Pack 约束的实践解析 导读 本文以 Slang 语言参考 docs/language refere编译器图形学编程语言TypeScript 剩余参数Rest Parameters完全指南语法、类型与编译原理TypeScript 剩余参数Rest Parameters完全指南语法、类型与编译原理 剩余参数Rest Parameters是 TypeScrip教程FluentValidation 10.0 升级指南泛型化重构与破坏性变更全解析FluentValidation 10.0 升级指南泛型化重构与破坏性变更全解析 导读 FluentValidation 10.0 是一次以「性能」与「类型后端上一篇终极指南3分钟掌握CrystalDiskInfo守护你的数据安全下一篇5步掌握sd-webui-additional-networks终极LoRA扩展配置指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

Agent记忆管理实战:基于MCP与Docker的hindsight落地指南

Agent记忆管理实战:基于MCP与Docker的hindsight落地指南

1. 从“hindsight”说起:为什么记忆是 Agent 落地的最后一公里第一次看到 “hindsight” 这个词,是在一个做智能体(Agent)的朋友群里。有人丢了一句:“你们有没有觉得,现在的 Agent 就像金鱼,聊…

📅 2026/9/28 7:31:01
一文搞懂软件开发里的CI技术:持续集成到底是个啥?为啥都在用?

一文搞懂软件开发里的CI技术:持续集成到底是个啥?为啥都在用?

开篇:一次"合并周" 一个 6 人的游戏项目组,做一个新版本。 大家分头开工,各开各的分支: 张三 → feature/新战斗系统 (改了 87 个文件) 李四 → feature/公会玩法 &#xff08…

📅 2026/9/28 7:31:01
新一代IDE Copilot X编程效率实测分析:TaoToken统一Key接入AI结对编程的范式革命

新一代IDE Copilot X编程效率实测分析:TaoToken统一Key接入AI结对编程的范式革命

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/28 7:31:01
MORE NEWS

更多资讯

📰

React Native异步状态更新与渲染机制全面解析

我先跟你说个特别真实的场景:RN 项目里调完setState,紧接着下一行打印this.state,结果拿到的还是旧数据。你以为是代码写错了,查了半天,发现不是 bug,是机制。状态更新是异步的,渲染是 React 自…

📰

Eclipse怎么做网页免费工具全解析:备案别花冤枉钱

Eclipse怎么做网页免费工具全解析:备案别花冤枉钱 备案流程一头雾水?很多人第一反应是找代办,结果一问多少钱,从几百到几千都有,心里没底。其实,对于用 Eclipse…

📰

浪网站制作对比评测:告别拖延,3招搞定技术选型

浪网站制作对比评测:告别拖延,3招搞定技术选型 改个按钮颜色,建站公司让你等一周?这种憋屈谁受得了? 别骂了,先看看你的网站是用什么技术堆的。很多老板不懂技术,只懂扔需求,结果被外包坑得底掉。今天咱们不整虚的,直接上硬菜,通过 对比评测…

📰

做网站需要提供什么条件?避开被黑挂马坑,选对哪家好

做网站需要提供什么条件?避开被黑挂马坑,选对哪家好 网站被黑挂马不知道怎么办?别慌,先自查。很多老板找建站公司,问“做网站需要提供什么条件”,结果只给了个Logo和几段文字,上线没三天,网站变成赌博广告,百度也搜不到,找服务商推诿,找技术不…

📰

小项目开发sop流程

文章目录从零开始做项目:一份完整的个人项目开发流程指南(以贪吃蛇为例)一、立项二、可行性分析技术可行性要分析什么?🌰 实战例子:开发一个贪吃蛇三、需求分析四、功能流程图五、产品原型图六、架构搭建为…

📰

S905L3SB盒子刷机指南:安卓9.0线刷固件+当贝桌面纯净版集成

如果你手里有一台运营商送的IPTV盒子,芯片方案是晶晨S905L3SB,那大概率你和我一样,拿到手没几天就被它自带桌面里的广告和推荐位烦得不行。开机先放十几秒广告,切个频道又弹个充值页面,想装个第三方App还被各种限制卡住…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬