深入理解 strictNullChecks:TypeScript Book 中的严格空值检查指南
文档教程【免费下载链接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.项目地址https://gitcode.com/gh_mirrors/typ/typescript-book点击查看免费下载strictNullChecks是 TypeScript 编译器中最影响日常开发体验的选项之一它决定了null与undefined是否会被当作普通值参与类型系统还是被严格隔离、仅在显式声明时才允许出现。本文以《The Concise TypeScript Book》中 strictNullChecks 章节 为核心结合仓库内类型系统、配置与配套语法章节系统讲解该选项的语义、配置方式、与null/undefined类型的关系以及在实际代码中配合使用的!、?.、??等工具帮助你彻底掌控空值处理。strictNullChecks 是什么根据 strictnullchecks.md 的定义strictNullChecks是 TypeScript 编译器的一个选项它强制进行严格的空值检查enforces strict null checking。当该选项被启用时变量variable和参数parameter只有在显式声明其类型为null | undefined联合类型时才允许被赋值为null或undefined。反过来如果某个变量或参数没有被显式声明为可空nullableTypeScript 就会在编译期生成错误从而提前阻止潜在的运行时错误runtime errors。这一行为可以概括为两条规则显式声明才能赋值可空性必须通过联合类型null | undefined明确写出编译器才允许传入空值未声明即报错任何未显式声明为可空的变量或参数接收到null/undefined时编译直接失败。例如在严格模式下下面的代码会报错// 显式声明为可空合法 const maybeName: string | null null; // 未声明为可空TypeScript 编译错误 // Type null is not assignable to type string const name: string null;这正是该选项的价值所在将“空值可能随时出现”这一隐患从运行时提前到编译期强制开发者显式处理空值路径。在类型系统中的地位null 与 undefined 的语义要理解strictNullChecks先要理解null与undefined在 TypeScript 类型系统中的语义。根据 primitive-types.md 的说明undefined表示值未被赋值或初始化即“非有意的值缺失”unintentional absence of valuenull表示我们明确知道该字段没有值即“有意的值缺失”intentional absence of value。在 exploring-the-type-system.md 的“类型作为集合”章节中undefined和null被归类为单元素集合Single element set与never空集合、boolean/union有限集合、string/number/object无限集合、any/unknown全集并列。这意味着每个空值类型只包含一个可能的取值它们的可赋值规则非常明确。更关键的是该书在同一章节明确给出了strictNullChecks对这两个类型行为的决定性影响请注意当启用strictNullChecks时null和undefined的处理方式与void类似否则它们与never类似。这段话揭示了两种模式下的本质差异编译选项状态null/undefined的表现实际效果strictNullChecks启用类似void是类型系统中真实存在的值类型只有显式声明为null/undefined或与之联合的变量才能接收空值strictNullChecks禁用类似never可以被赋值给任意类型任何类型都“假装”接受null/undefined空值检查形同虚设也就是说关闭该选项后null和undefined几乎可以赋给任何类型像never一样具有极强的可赋值性此时类型系统无法约束空值的扩散而开启后它们被限制在显式声明的联合类型内类型系统得以精准追踪每个可空位置。如何启用tsconfig.json 与 CLIstrictNullChecks的启用方式有两种写入tsconfig.json或通过tsc命令行参数传递。在日常项目中推荐将其纳入strict严格模式统一管理。通过 strict 严格模式启用本项目tools目录下的 tsconfig.json 是实际启用了严格模式的示例{ compilerOptions: { target: es2022, module: commonjs, noImplicitAny: true, esModuleInterop: true, noEmitOnError: true, moduleDetection: force, noUnusedLocals: false, forceConsistentCasingInFileNames: true, strict: true, skipLibCheck: true, lib: [es2022, esnext.disposable, esnext.decorators, dom] } }其中第 11 行的strict: true会一次性启用包括strictNullChecks在内的一组严格检查选项。网站部分则在 website/tsconfig.json 中通过继承 Astro 的严格预设开启{ extends: astro/tsconfigs/strict }单独开启或关闭如果不想启用整套严格模式也可以只针对该选项单独配置{ compilerOptions: { strictNullChecks: true } }将值改为false则单独关闭空值检查。同样的效果可以通过 CLI 达成tsc --strictNullChecks需要说明的是strictNullChecks的效果与项目实际使用的 TypeScript 版本密切相关本文讨论的行为以仓库 tools/package.json 中锁定的typescript ^5.4.5为基准。开启前后的行为对比结合 exploring-the-type-system.md 中“记住这些规则”一节的赋值示例可以看到可赋值性的完整图谱let a: number 1; let b: number 2; a b; // 合法一切都可以赋值给自己 let c: any; c 1; // 合法所有类型都可以赋给 any let d: unknown; d 1; // 合法所有类型都可以赋给 unknown let e: unknown; let e1: unknown e; // 合法unknown 只能赋给自身和 any let e2: any e; // 合法 let e3: number e; // 非法 let f: never; f 1; // 非法没有任何值可以赋给 never let g: void; let g1: any; g 1; // 非法void 除了 any 之外不接受也不可赋给任何类型 g g1; // 合法结合该章节的注释可以得出在启用strictNullChecks的项目中null与undefined的赋值行为应当类比void——它们只在显式声明的上下文中流转不会“悄悄”渗入其他类型。这也是为什么开启后类似document.getElementById(...)的 API 返回值会包含null分支从而迫使开发者处理“元素可能不存在”的路径。实际开发中的配套工具启用strictNullChecks后空值会频繁出现在类型中TypeScript 也提供了配套语法让处理更简洁。《The Concise TypeScript Book》在 others.md 中系统介绍了这些工具。Non-null Assertion 运算符后置!后置!用于向编译器断言某个变量或属性不是null或undefined即便静态类型分析认为它可能是。该功能可以消除一部分显式的空值检查type Person { name: string; }; const printName (person?: Person) { console.log(Name is ${person!.name}); };如上例所示person是可选参数类型为Person | undefined通过person!.name我们向编译器承诺此时person必然存在。需要强调的是!只是编译期断言不产生任何运行时保护——若实际值为空运行时依然会抛错因此应谨慎使用。可选链?.可选链运算符?.与普通点运算符.用法类似区别在于它安全地处理null/undefined当左侧值为空时整个表达式短路并返回undefined而不是抛出错误type Person { name: string; age?: number; address?: { street?: string; city?: string; }; }; const person: Person { name: John, }; console.log(person.address?.city); // undefined在严格空值检查下person.address的类型是{ street?: string; city?: string } | undefined?.让我们无需逐层if判断即可安全访问深层属性。空值合并运算符??空值合并运算符??在左侧为null或undefined时返回右侧值否则返回左侧值——注意它只对null/undefined生效不会像||那样把0、、false等 falsy 值一并替换const foo null ?? foo; console.log(foo); // foo const baz 1 ?? baz; const baz2 0 ?? baz; console.log(baz); // 1 console.log(baz2); // 0??与strictNullChecks配合是“为可空值提供默认值”的标准写法且不会误伤合法的 falsy 值。可选属性?与类型收窄除了上述运算符书中 optional-properties.md 章节讲解的可选属性语法prop?: T本质上是prop: T | undefined与strictNullChecks直接相关。同时narrowing.md 与 control-flow-analysis.md 介绍了通过typeof检查、truthiness 判断、in运算符、instanceof等方式在代码流中收窄可空类型的方法例如let x: number | undefined 10; if (x ! undefined) { x 100; // 此处 x 已被收窄为 number }这类控制流收窄是strictNullChecks模式下处理空值的主力手段能让代码在保持安全的同时清晰表达“空值已被排除”的意图。在本书中的位置与延伸阅读strictNullChecks在《The Concise TypeScript Book》中位于 目录 的第 19 章紧随 “Literal Inference” 之后处于类型系统基础概念向进阶类型语法过渡的关键位置。围绕它书中提供了完整的知识链路前置基础primitive-types.mdnull/undefined语义、exploring-the-type-system.md类型系统与可赋值性核心章节strictnullchecks.md本文主题进阶衔接narrowing.md空值收窄、optional-properties.md可选属性、unknown-type.md类型安全的unknown、the-never-type.mdnever与穷尽性检查。此外本书为多语言开源项目本文依据的保加利亚语章节与英文原版 strictnullchecks.md 内容一致除保加利亚语外网站内容目录 下还维护了阿拉伯语、中文、日语、韩语、俄语等十余种语言的对应章节便于不同语言背景的读者对照学习。小结strictNullChecks是 TypeScript 严格模式中最具“行为改变力”的开关开启后null与undefined从可随意赋值的“隐形值”变为必须显式声明才能出现的“一等类型”其行为类比void关闭时则退化为类似never的宽松语义。配合!、?.、??以及控制流收窄开发者可以在编译期获得完整的空值追踪能力将大量运行时崩溃前置为编译错误——这正是 TypeScript 相比纯 JavaScript 的核心价值之一。赞分享文档教程【免费下载链接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.项目地址https://gitcode.com/gh_mirrors/typ/typescript-book点击查看免费下载相关推荐TypeScript Book 实战指南strictNullChecks 严格空值检查全面解析TypeScript Book 实战指南strictNullChecks 严格空值检查全面解析 本文是《TypeScript Book》开源仓库中 docs/教程TypeScript strictNullChecks 严格空值检查详解以 The Concise TypeScript Book 项目为实践范本TypeScript strictNullChecks 严格空值检查详解以 The Concise TypeScript Book 项目为实践范本 stric文档教程如何开启Flow严格模式提升JavaScript代码质量的完整指南如何开启Flow严格模式提升JavaScript代码质量的完整指南 Flow是一个为JavaScript添加静态类型检查的工具能够显著提升开发者生产力和代码开发工具静态分析代码质量上一篇vim-airline会话自动命名规则自定义格式下一篇Argo CD如何重构企业级多团队Kubernetes部署安全边界创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考