- 文档
- 教程
【免费下载链接】typescript-book
The Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.
strictNullChecks是 TypeScript 编译器的一项关键选项,用于强制进行严格的null/undefined检查。本指南围绕 The Concise TypeScript Book(波兰语版 strictnullchecks.md)的核心定义展开,并结合仓库内源码与配置,深入讲解该选项的工作原理、在tsconfig.json中的配置方式、与联合类型、类型收窄(narrowing)、unknown/never等类型的协同关系,以及在实际开发中的最佳实践。
1. 什么是 strictNullChecks?
strictNullChecks是 TypeScript 编译器选项,用于启用对null和undefined的严格检查。当该选项开启时:
- 变量和参数只有显式声明了联合类型
null | undefined(或其中某个成员),才能被赋值为null或undefined; - 如果变量或参数未显式声明为“可为空”(nullable),TypeScript 就会在编译阶段报错,从而在运行时错误发生之前将其拦截。
换言之,该选项让null和undefined成为显式、可控的值,而非悄悄混入任何类型中。
从“集合论视角”看(详见本书 exploring-the-type-system.md 的 “Types as Sets” 一节):每个类型都是一组可能值的集合,null与undefined分别是单元素集合。开启 strictNullChecks 后,只有当目标类型包含这些元素时(例如null | undefined联合),赋值才合法。
2. 在 tsconfig.json 中如何启用
strictNullChecks通常无需单独设置,因为更常见的做法是直接启用strict标志。strict是一个“全家桶”选项,开启后会自动启用包括strictNullChecks在内的多项严格检查。
在本书项目中可以找到真实例证:
- tools/tsconfig.json 设置了
"strict": true,并配合"target": "es2022"、"noImplicitAny": true、"noEmitOnError": true等选项; - website/tsconfig.json 通过
"extends": "astro/tsconfigs/strict"继承了 Astro 的严格配置,同样包含 strictNullChecks。
显式写法如下:
{ "compilerOptions": { "strict": true, "strictNullChecks": true } }如果你只想启用空值检查而保持其他宽松选项,可以单独设置:
{ "compilerOptions": { "strictNullChecks": true } }注意:当
strictNullChecks为true时,null/undefined会被当作类似void的类型处理;而当其为false时,它们的行为则类似never。这一点在本书 exploring-the-type-system.md 中有明确说明。
3. 启用前后的行为对比
3.1 关闭时(宽松模式)
let name: string; name = null; // 不报错 name = undefined; // 不报错在这种模式下,null和undefined可以赋给任何类型,许多运行时崩溃(如Cannot read properties of null)要到浏览器/Node 运行时才暴露。
3.2 开启时(严格模式)
let name: string; name = null; // Error: Type 'null' is not assignable to type 'string'. name = undefined; // Error: Type 'undefined' is not assignable to type 'string'.开启后,未声明为可空的变量无法接收null或undefined。
3.3 显式声明可空
let name: string | null = null; // 合法 let age: number | undefined; // 合法(undefined 可省略声明?不,需显式) let nickname: string | null | undefined; // 合法当变量或参数使用联合类型null | undefined(或仅包含其中之一)显式声明后,赋值null/undefined才被允许。
4. 对函数参数与返回值的影响
strictNullChecks 同样作用于函数参数和返回值:
// 参数显式可空 const find = (id: string | null): string => { return id === null ? 'not found' : `id: ${id}`; }; // 返回值可能为 null const getUser = (id: number): { name: string } | null => { if (id <= 0) return null; return { name: 'Alice' }; };如果没有显式声明可空,却又返回null,编译器会报错:
const getUser = (id: number): { name: string } => { if (id <= 0) return null; // Error return { name: 'Alice' }; };5. 与 unknown / never / void 的关系
开启 strictNullChecks 后,null和undefined在赋值规则上有了明确边界。本节相关类型在本书中各有专章:
- unknown-type.md:
unknown只能赋给any和自身。它是any的类型安全替代品。例如let value3: boolean = value; // Invalid。 - the-never-type.md:
never表示“永远不可能的值”。例如当变量被收窄到不可能存在的类型时,编译器会推断其为never。 - void-type.md:
void表示函数不返回任何值。开启 strictNullChecks 后,void与null/undefined的区分尤其重要——一个返回void的函数不能被当作返回null的函数使用。
下面是本书 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;否则它们的行为类似never。这正是该选项改变赋值规则的根本原因。
6. 配合类型收窄(Narrowing)使用
strictNullChecks 只有在配合类型收窄时,才能既保证安全又保持便利。本书 narrowing.md 专门讲解了收窄的多种方式。
6.1 条件收窄
let x: number | undefined = 10; if (x !== undefined) { x += 100; // 此处 x 被收窄为 number }6.2 truthiness 收窄
const toUpperCase = (name: string | null) => { if (name) { return name.toUpperCase(); // name 被收窄为 string } else { return null; } };6.3 提前返回 / 抛出错误
let x: number | undefined = 10; if (x === undefined) { throw 'error'; } x += 100; // 此处 x 已收窄为 number6.4 自定义类型守卫(Type Predicate)
const isValid = (item: string | null): item is string => item !== null; const data = ['a', null, 'c', 'd', null, 'f']; const r2 = data.filter(isValid); // 类型为 string[],成功收窄7. 实战中的常见模式与陷阱
7.1 可选属性与?语法
interface User { name: string; email?: string | null; // 可选且显式可空 } const u: User = { name: 'Alice', email: null }; // 合法注意:email?: string表示“可能不存在”,并不等同于“可能是null”。要允许null,需要显式写成email?: string | null。
7.2 非空断言!
当你比编译器更清楚某个值不可能为null时,可以使用非空断言:
const input = document.getElementById('my_input')!; // 断言非空 input.value = 'hello';这是 strictNullChecks 下最常用的“逃生舱”,但应谨慎使用——它相当于告诉编译器“跳过检查”,滥用会重新引入运行时风险。
7.3 用类型别名简化可空声明
type Nullable<T> = T | null; type Maybe<T> = T | undefined; let a: Nullable<string>; // string | null let b: Maybe<number>; // number | undefined7.4 可选链与空值合并
const user = { address: { city: 'Warsaw' } }; const city = user?.address?.city; // string | undefined const display = city ?? 'unknown'; // 提供默认值?.可选链:当左侧为null/undefined时短路返回undefined;??空值合并:仅在左侧为null/undefined时取右侧默认值。
7.5 常见陷阱
- 忘记把
null纳入联合类型:let s: string = null;在严格模式下会报错; - 数组元素也可能为空:
(string | null)[]与string[]完全不同; - 库的
.d.ts声明未标可空时,调用其 API 返回null也会报错,此时需检查声明或用断言处理。
8. 从源码看 strictNullChecks 的实际运用
在 The Concise TypeScript Book 仓库中,strictNullChecks 的效果可以直接从配置与代码中验证:
- tools/tsconfig.json:
"strict": true,用于构建书籍工具的 TypeScript 代码; - website/tsconfig.json:继承
astro/tsconfigs/strict; - website/src/content/docs/book/exploring-the-type-system.md:明确写出“开启 strictNullChecks 时,
null/undefined类似void”这一行为描述,可作为理解该选项语义的原始依据; - website/src/content/docs/book/the-never-type.md 与 website/src/content/docs/book/unknown-type.md:展示了在严格模式下与
null相邻的边界类型行为。
此外,本书的 table-of-contents.md 将 strictNullChecks 编排在“Poznawanie systemu typów”(探索类型系统)章节,与之并列的内容还包括类型推断、类型收窄、联合类型等,说明该选项是理解 TypeScript 类型系统的基础环节之一。
9. 总结
| 要点 | 说明 |
|---|---|
| 选项位置 | tsconfig.json→compilerOptions |
| 开启方式 | "strictNullChecks": true或"strict": true |
| 核心语义 | null/undefined只能赋给显式声明为可空的类型 |
| 未声明可空时赋值 | 编译报错,拦截潜在运行时错误 |
| 可空声明方式 | 联合类型T \| null、T \| undefined、T \| null \| undefined、可选属性? |
| 常见配合 | 类型收窄、!非空断言、?.可选链、??空值合并、类型守卫 |
| 行为类比 | 开启时null/undefined类似void;关闭时类似never |
strictNullChecks是 TypeScript 迈向类型安全的关键一步。启用后,代码中的“空值”不再隐晦,而是成为类型系统可感知、可约束、可收窄的一部分,从而把大量潜在的运行时错误提前到编译期解决。建议在所有新项目中直接启用strict(包含 strictNullChecks),并配合本书介绍的收窄与类型守卫技巧,写出既安全又流畅的 TypeScript 代码。
- 文档
- 教程
【免费下载链接】typescript-book
The Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.
相关推荐
TypeScript Book 实战指南:strictNullChecks 严格空值检查全面解析
TypeScript Book 实战指南:strictNullChecks 严格空值检查全面解析 本文是《TypeScript Book》开源仓库中 docs/
教程strictNullChecks 详解:TypeScript 严格空值检查的配置、原理与实战
strictNullChecks 详解:TypeScript 严格空值检查的配置、原理与实战 strictNullChecks 是 TypeScript 编译器
文档教程TypeScript strictNullChecks 全面解析:The Concise TypeScript Book 中的严格空值检查实战指南
TypeScript strictNullChecks 全面解析:The Concise TypeScript Book 中的严格空值检查实战指南 strict
文档教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考