TypeScript开启严格空值检查:避免 null/undefined 运行时报错

咖啡半糖
咖啡半糖
发布时间:2026-10-16| 8人浏览过
原创

TypeScript 默认允许 null 和 undefined 赋值给任何类型,这容易引发运行时“空指针”错误。本文将详细介绍如何通过启用 strictNullChecks 编译器选项开启严格模式,并使用联合类型与可选属性安全地处理可为空的变量。

一、理解 TypeScript 的空值处理

在 JavaScript 中,null 和 undefined 是两个基础的值。在 TypeScript 中,它们各自拥有独立的类型 undefined 和 null。然而,默认情况下(即 strictNullChecks 为 false),它们被视为所有类型的子类型。

这意味着以下代码在默认设置下完全合法:

let u: undefined = undefined;
let n: null = null;

例如:

let userName: string;
userName = "搞前端的半夏"; // OK
userName = null;      // OK
userName = undefined; // OK

let age: number;
age = 18;        // OK
age = null;      // OK (可能引发后续逻辑错误)
age = undefined; // OK

虽然编译通过,但这种写法掩盖了潜在的运行错误。TypeScript 2.0 引入了严格空值检查,旨在将这类问题拦截在编译阶段。

二、开启严格空值检查 (strictNullChecks)

开启此功能后,null 和 undefined 将无法再隐式赋值给其他具体类型,必须显式声明。

第1步:在 tsconfig.json 中启用配置

  • 目的:修改项目编译规则,激活严格的空值验证。
  • 入口:项目根目录下的 tsconfig.json 文件。
  • 动作:找到 compilerOptions 区块,添加或修改 strictNullChecks 为 true。
{
  "compilerOptions": {
    "strictNullChecks": true
  }
}

完成状态判断:保存文件后,TypeScript 编译器将立即报错之前的赋值操作。例如,下面的代码将显示错误:

let userName: string;
userName = null;      // 错误: Type 'null' is not assignable to type 'string'.
userName = undefined; // 错误: Type 'undefined' is not assignable to type 'string'.

注意点:开启严格模式并不意味着不能使用 null 和 undefined,而是要求你明确声明变量的类型包含它们。

第2步:理解严格模式下的类型系统

如果你希望一个变量专门只接收空值,是可以的,但通常我们面对的是“可能有值,也可能为空”的场景。

// 仅在需要单独表示空类型时使用,较为少见
let userName: null;
userName = null;

let age: undefined;
age = undefined;

三、如何安全地定义可空类型变量

在实际开发中,我们经常遇到用户名、年龄等字段可能为空的情况。此时不能简单地将类型设为 string,而应采用联合类型或可选属性。

方法1:使用联合类型 (Union Types)

联合类型允许一个变量接受多种类型。要解决上文的报错,需要将变量类型定义为 string | null 或 string | undefined。

示例:声明 username 可接受字符串或 null

let userName: string | null;
userName = "搞前端的半夏"; // OK
userName = null;           // OK
userName = undefined;      // 错误: Type 'undefined' is not assignable to type 'string | null'.

这种方式明确了该变量只能存这两种情况,若尝试存入其他类型或遗漏检查,编译器都会提示。

方法2:使用对象可选属性标记 (?)

在处理数据模型时,经常使用接口或类型定义对象。如果对象的某个属性是可选的,可以使用 ? 修饰符。

场景演示:

如果不加 ?,即使我们写了联合类型:

type User = {
  name: string;
  age: number | undefined;
};

// 正确用法
let user1: User = { name: "搞前端的半夏", age: undefined };
let user2: User = { name: "搞前端的半夏", age: 18 };

但如果创建对象时完全不传 age:

let user3: User = { name: "搞前端的半夏" }; // 编译错误,缺少 age

为了实现“可以不传这个字段”,我们需要将其设为可选属性。此时,TypeScript 会自动将 undefined 加入联合类型,即相当于类型为 number | undefined。

type User = {
  name: string;
  age?: number; // 使用 ? 标记为可选
};

完整验证:

// 三种方式全部通过编译
let user1: User = { name: "搞前端的半夏", age: undefined };
let user2: User = { name: "搞前端的半夏", age: 18 };
let user3: User = { name: "搞前端的半夏" }; 

四、安全访问:避免运行时崩溃

开启严格检查后,如果我们定义的变量包含 null 或 undefined,直接访问其属性会触发编译报错。这正是 TypeScript 保护我们的地方。

第1步:识别潜在风险

下面这段代码试图获取用户名的长度,但编译器不知道传入的 userName 是否真的存在:

function UserNameLength(userName: string | null) {
  return userName.length; // 错误: Object is possibly 'null'
}

第2步:执行安全检查(防御性编程)

在使用变量之前,必须先判断它是否为空。这是最基础的“空值校验”。

function UserNameLength(userName: string | null) {
  if (userName !== null) {
    // 只有在这里,userName 才会被收窄为 string 类型
    return userName.length; 
  }
  return 0;
}

进阶:可选链操作符 (Optional Chaining) ?.
在访问深层嵌套对象的可空属性时,可以使用 ?. 简化逻辑,如果前面的属性不存在则返回 undefined 而不报错。

五、处理函数参数的可空调用

在回调函数场景中,参数可能为 undefined。例如定义一个带可选回调的函数:

function fn(callback?: () => void) {
  callback(); // 编译错误: 'callback' is possibly 'undefined'
}

如果在调用处不传参数,进入内部时 callback 就是 undefined,直接执行会抛错。调用端也会报错:

解决方案:
在调用前确保函数不为空。

function fn(callback?: () => void) {
  if (callback) {
    callback();
  }
}

// 或者直接使用可选调用语法
function fn(callback?: () => void) {
  callback?.(); 
}
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。