TypeScript开启严格空值检查:避免 null/undefined 运行时报错
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?.();
}免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









