news 2026/9/28 2:43:00

strictNullChecks 全面指南:TypeScript 严格空检查的原理与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
strictNullChecks 全面指南:TypeScript 严格空检查的原理与实战
  • 文档
  • 教程

【免费下载链接】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
点击查看免费下载

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 已收窄为 number

6.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 | undefined

7.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.

项目地址:https://gitcode.com/gh_mirrors/typ/typescript-book
点击查看免费下载
上一篇:如何使用贝叶斯逻辑回归:机器学习中的概率分类利器
下一篇:Duix.Avatar 免费本地部署:一段10秒视频克隆数字人,全离线生成 AI 视频

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 2:42:43

公司做网站要花多少钱:从零搭建的安全成本全景解析

公司做网站要花多少钱:从零搭建的安全成本全景解析 备案流程一头雾水,是不是让你觉得从零搭建公司官网简直是一场噩梦?别慌,很多老板以为网站开发最贵的是代码或设计,其实真正的隐形成本往往藏在安全配置和合规细节里。根据腾讯云开发者社区发布的《企业上云安全最佳实践》,超过60%的中小企业网站在上线首年遭遇的…

作者头像 李华
网站建设 2026/9/28 2:42:40

青岛百度优化哪家好?3步搞定技术选型避坑指南

青岛百度优化哪家好?3步搞定技术选型避坑指南 改个需求建站公司拖一周,这种憋屈事儿在青岛做网站优化的圈子里太常见了。很多老板找了一圈,问了一圈,最后就卡在 青岛百度优化哪家好 这个问题上,其实不是找不到好公司,而是你没搞懂背后的技术底层。…

作者头像 李华
网站建设 2026/9/28 2:42:33

避开模板坑,怎样做教育视频网站及建站报价真相

避开模板坑,怎样做教育视频网站及建站报价真相 很多做教育的朋友跟我吐槽,找外包公司做教育视频网站,交出来的东西跟淘宝9.9包邮的模板一模一样。视频播放器卡得要死,后台管理乱成一锅粥,最要命的是,那UI设计得简直辣眼睛,完全撑不起品牌的调性。 模板网站太丑不够用…

作者头像 李华