基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

null 和 undefined 在 TypeScript 中是如何处理的?

知识点图片

在 TypeScript 中,nullundefined 的处理方式主要取决于编译选项 strictNullChecks 的设置。这是 TypeScript 类型系统中最关键的概念之一。

以下是详细的解释:

1. 基础概念

在 JavaScript 中:

  • undefined:表示变量已声明但尚未赋值,或者对象属性不存在。
  • null:表示一个有意的“空值”或“无对象”。

在 TypeScript 中,nullundefined 既是,也是类型

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

2. strictNullChecks 编译选项

这是决定 TypeScript 如何处理这两个值的核心开关。

情况 A:strictNullChecks: false (非严格模式)

这是早期 TypeScript 的默认行为(现在不推荐)。在这种模式下,nullundefined所有类型的子类型

这意味着你可以把 nullundefined 赋值给 numberstring 等任何类型。

typescript
// strictNullChecks: false
let num: number;
num = 1;         // OK
num = null;      // OK (不会报错)
num = undefined; // OK (不会报错)

// 危险:这可能导致运行时错误 "Cannot read property ... of null"
num.toFixed(2); // 如果 num 是 null,这里运行时会炸

情况 B:strictNullChecks: true (严格模式,推荐)

在现代 TypeScript 项目中,通常都会开启此选项(或者开启 strict: true)。

在这种模式下,nullundefined 不再是其他类型的子类型。它们是独立的类型。

typescript
// strictNullChecks: true
let num: number;
num = 1;         // OK
num = null;      // Error: Type 'null' is not assignable to type 'number'.
num = undefined; // Error: Type 'undefined' is not assignable to type 'number'.

如果你想让一个变量既可以是数字也可以是空,必须显式使用联合类型 (Union Types)

typescript
let num: number | null;
num = 1;    // OK
num = null; // OK

3. 常用操作符与语法

在严格模式下处理 nullundefined 时,TypeScript 提供了一系列工具来简化代码:

A. 可选参数与属性 (?)

在函数参数或接口属性后加 ?,会自动包含 | undefined(注意:通常不包含 null,除非显式声明)。

typescript
function printName(name?: string) {
  // name 的类型是 string | undefined
  console.log(name);
}

interface User {
  id: number;
  email?: string; // 类型是 string | undefined
}

B. 可选链操作符 (Optional Chaining ?.)

安全地访问可能为 nullundefined 的对象属性。

typescript
let user: User | null = null;

// 如果 user 是 null,代码不会崩溃,而是返回 undefined
const email = user?.email; 

C. 空值合并操作符 (Nullish Coalescing ??)

当左侧操作数为 nullundefined 时,返回右侧的操作数。这比 || 更安全(|| 会把 0"" 也视为假值)。

typescript
const input = null;
const value = input ?? "Default Value"; // 结果: "Default Value"

const count = 0;
const validCount = count ?? 100; // 结果: 0 (如果是 count || 100,结果会是 100)

D. 非空断言操作符 (Non-null Assertion !)

当你确定某个变量此时一定不是 nullundefined,但 TypeScript 无法自动推断出来时,可以使用 ! 告诉编译器“相信我,它有值”。

typescript
const myString: string | null = "Hello";

// 编译器可能认为它是 null,但如果你确定它不是:
const length = myString!.length; 

注意:慎用 !,因为它会绕过类型检查,如果运行时真的是 null,程序会崩溃。


4. 类型收窄 (Type Narrowing)

在使用联合类型(如 string | null)时,你需要先检查它不是 null,才能像使用 string 一样使用它。这叫“类型收窄”。

typescript
function doSomething(value: string | null) {
  // value.toUpperCase(); // Error: value 可能为 null

  if (value !== null) {
    // 在这个块级作用域内,TS 知道 value 一定是 string
    console.log(value.toUpperCase()); 
  }
}

5. void vs undefined

  • undefined: 是一个具体的类型和值,表示变量未定义。
  • void: 专门用于表示函数没有返回值
typescript
function logMessage(): void {
  console.log("Hi");
  // 实际上返回的是 JavaScript 的 undefined,但在 TS 类型系统中它叫 void
}

总结

  1. 始终开启 strictNullChecks(或 strict 模式)。这是编写健壮 TypeScript 代码的基础。
  2. 如果一个值可能不存在,显式声明为 Type | nullType | undefined
  3. 利用 ?.?? 来优雅地处理空值。
  4. 利用 类型收窄 (if check) 来安全地使用可能为空的变量。
00:00
00:00