在 TypeScript 中,我们经常会遇到一些变量或属性可能为空的情况。当我们使用这些变量或属性时,TypeScript 会提示我们进行非空判断,以避免出现空指针异常。但是,在某些情况下,我们确信一个变量或属性不为空,但 TypeScript 仍然会提示我们进行非空判断。为了解决这个问题,TypeScript 引入了非空断言(Non-Null Assertion)语法。
什么是非空断言?
非空断言是 TypeScript 中的一种语法,用于告诉编译器一个变量或属性不为空。它的语法是在变量或属性名称后面加上一个感叹号(!)。
例如:
let name: string | undefined = undefined; console.log(name.length); // 编译错误:Object is possibly 'undefined'. let age: number | undefined = 18; console.log(age!.toString()); // 不会出现编译错误
在上面的代码中,我们定义了两个变量 name
和 age
,它们的类型都是 string | undefined
和 number | undefined
。当我们尝试使用 name.length
时,TypeScript 会提示我们 Object is possibly 'undefined'
,因为 name
可能为空。但是当我们使用 age!.toString()
时,TypeScript 不会提示错误,因为我们使用了非空断言语法告诉编译器 age
不为空。
需要注意的是,使用非空断言语法需要非常谨慎,因为它会关闭 TypeScript 的类型检查,可能会导致运行时错误。
非空断言的使用场景
非空断言通常用于以下场景:
1. 初始化变量或属性时
在某些情况下,我们可能无法在声明变量或属性时就确定它们的值,但是我们又希望在后面使用它们时不出现编译错误。这时,我们可以使用非空断言语法告诉编译器这些变量或属性不为空。
例如:
let name!: string; // ... name = getNameFromServer(); // 在某个时刻从服务器获取名字 console.log(name.length); // 不会出现编译错误
在上面的代码中,我们使用非空断言语法告诉编译器 name
不为空,然后在后面的代码中给它赋值。虽然在声明时我们不知道 name
的值,但是我们确信在后面的代码中它会被正确地初始化,因此可以使用非空断言语法。
2. 类型断言时
在 TypeScript 中,我们可以使用类型断言(Type Assertion)来告诉编译器一个变量的类型。当我们确定一个变量的类型时,可以使用非空断言语法告诉编译器这个变量不为空。
例如:
const obj: unknown = { name: 'Tom', age: 18 }; const name = (obj as { name: string }).name!; console.log(name.length); // 不会出现编译错误
在上面的代码中,我们使用类型断言将 obj
的类型指定为 { name: string }
,然后使用非空断言语法告诉编译器 name
不为空。
非空断言的注意事项
虽然非空断言语法可以帮助我们避免一些繁琐的非空判断,但是需要注意以下几点:
1. 使用时需要非常谨慎
使用非空断言语法会关闭 TypeScript 的类型检查,可能会导致运行时错误。因此,在使用非空断言语法时需要非常谨慎,确保变量或属性不为空。
2. 不能用于 null 或 undefined
非空断言语法只能用于非 null 和 undefined 类型的变量或属性。如果一个变量或属性可能为 null 或 undefined,那么使用非空断言语法是不安全的。
例如:
let name: string | null = null; console.log(name!.length); // 运行时错误:Cannot read property 'length' of null.
在上面的代码中,我们定义了一个变量 name
,它的类型是 string | null
。虽然我们使用了非空断言语法告诉编译器 name
不为空,但是在运行时仍然会出现错误,因为 name
的值为 null。
3. 使用可选链运算符更安全
在 TypeScript 3.7 中,引入了可选链运算符(Optional Chaining)语法,它可以更安全地访问可能为空的变量或属性。如果一个变量或属性可能为空,那么使用可选链运算符比使用非空断言语法更安全。
例如:
const obj: { name?: string } = {}; console.log(obj.name?.length); // 不会出现编译错误
在上面的代码中,我们定义了一个对象 obj
,它有一个可选的属性 name
。当我们使用 obj.name?.length
时,如果 name
为空,那么表达式的值为 undefined,不会出现运行时错误。
总结
非空断言是 TypeScript 中的一种语法,用于告诉编译器一个变量或属性不为空。使用非空断言语法需要非常谨慎,因为它会关闭 TypeScript 的类型检查,可能会导致运行时错误。在某些情况下,使用可选链运算符比使用非空断言语法更安全。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/65795af3d2f5e1655d361f34