【TypeScript】`null` 与 `undefined` 详解及其在严格空检查中的应用

TypeScript 是 JavaScript 的超集,它在 JavaScript 的基础上添加了静态类型检查,极大地提升了开发者的代码质量和开发效率。其中,nullundefined 作为 JavaScript 中两个用于表示“值不存在”的原始类型,在 TypeScript 中也有重要的应用。本文将围绕 nullundefined,以及它们在 TypeScript 中的使用展开讨论,并探讨 strictNullChecks 这一关键选项如何影响它们的行为。

一、JavaScript 中的 nullundefined

在 JavaScript 中,nullundefined 都是表示“没有值”的两种类型。

  1. null: 是一个赋值给变量的特殊值,表示该变量现在没有任何值。它是一个有意设定的空值,通常用来指示某些事情的缺失,比如查询未找到结果等。

    let myVar = null;
    
  2. undefined: 则表示变量尚未被赋值。变量在声明但未初始化时默认值为 undefined

    let anotherVar;
    console.log(anotherVar); // 输出 undefined
    

这两种值在 JavaScript 中经常用于不同的场景,但由于没有严格的类型检查机制,它们有时会导致一些难以察觉的错误。这就是 TypeScript 引入严格空检查(strictNullChecks)的原因。

二、TypeScript 中的 nullundefined

在 TypeScript 中,nullundefined 也是原始类型,它们的使用在一定程度上取决于 TypeScript 配置中的 strictNullChecks 选项。

1. strictNullChecks 关闭时

如果 strictNullChecks 被关闭,nullundefined 可以被赋值给任意类型的变量。这类似于 JavaScript 的默认行为,也就是没有严格区分 nullundefined 和其他类型。在这种模式下,可能会无意中将 nullundefined 分配给一个非空值,导致潜在的运行时错误。

let myString: string;
myString = null; // 在 strictNullChecks 关闭时合法
myString = undefined; // 合法

关闭 strictNullChecks 时,开发者可以更随意地处理 nullundefined,但缺乏对这些特殊值的严格检查往往会导致难以调试的错误。因此,通常建议在实际项目中开启 strictNullChecks

2. strictNullChecks 开启时

strictNullChecks 选项打开时,nullundefined 会被视为与其他类型完全不同的类型,不能随意赋值给其他类型的变量。开发者需要在使用这些变量之前,显式地检查它们的值。这种严格的类型检查可以帮助避免由于 nullundefined 导致的错误。

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

在这种情况下,必须通过类型收缩或者其他检查手段来处理可能为 nullundefined 的情况。例如:

function greet(name: string | null) {
  if (name === null) {
    console.log("Hello, guest!");
  } else {
    console.log(`Hello, ${name.toUpperCase()}!`);
  }
}

三、非空断言运算符(Postfix !

有时候,我们非常确定某个变量不会是 nullundefined,但 TypeScript 的类型系统无法推断出来。这时我们可以使用非空断言运算符 !,它可以告诉编译器“我知道这个值不是 nullundefined,请放心使用它”。

function processInput(input?: string | null) {
  console.log(input!.toUpperCase()); // 非空断言: 告诉编译器 input 肯定不为 null 或 undefined
}

然而,非空断言运算符应当谨慎使用,因为它不会对运行时的实际值做任何检查。如果我们误用了这个运算符,在运行时输入为 nullundefined 时,会导致程序崩溃。

processInput(null); // 运行时错误: Cannot read property 'toUpperCase' of null

因此,尽管 ! 是一个强大的工具,但在实际使用中我们应当小心,确保只有在绝对确定的情况下才使用它。

四、TypeScript 枚举类型

TypeScript 提供了 enum 关键字,允许我们定义一组命名的常量,这些常量代表特定的数值。在某些情况下,枚举类型可以帮助我们更清晰地表达代码意图。

例如,假设我们需要定义一个代表颜色的类型,我们可以通过枚举来实现:

enum Color {
  Red,
  Green,
  Blue
}

let c: Color = Color.Green;
console.log(c); // 输出 1

枚举不仅仅是类型系统中的一种概念,它也会在 JavaScript 的运行时生成实际的代码。因此,虽然它是 TypeScript 的特性之一,但它对实际执行的代码也有影响。

字符串枚举

TypeScript 还支持字符串枚举,它与常规枚举的区别在于,它的每个枚举成员都存储为字符串常量,而不是数值。

enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT"
}

let d: Direction = Direction.Left;
console.log(d); // 输出 'LEFT'

五、不常见的原始类型:bigintsymbol

除了常见的 nullundefinednumberstring 这些原始类型外,JavaScript 和 TypeScript 还支持一些不太常见的原始类型,比如 bigintsymbol

1. bigint

bigint 是 ES2020 中引入的用于表示任意精度整数的原始类型。它允许开发者处理比 number 类型更大的整数。

const largeNumber: bigint = BigInt(9007199254740991); // 通过 BigInt 函数创建
const anotherLargeNumber: bigint = 9007199254740991n; // 通过字面量语法创建

bigint 的出现解决了 JavaScript 中 number 类型最大值的限制问题(2^53 - 1),因此在需要处理非常大的整数时,bigint 是一个理想的选择。

2. symbol

symbol 是 JavaScript 中的另一个特殊原始类型。它用于创建唯一的标识符,通常用于对象属性名,以避免属性名的冲突。

const uniqueKey1 = Symbol('key');
const uniqueKey2 = Symbol('key');

console.log(uniqueKey1 === uniqueKey2); // 输出 false

每次调用 Symbol() 时都会创建一个独一无二的 symbol 值,因此它特别适合用于需要唯一标识的场景。

六、总结

TypeScript 提供了强大的类型检查机制,帮助我们在编写代码时及早发现潜在的错误。通过 nullundefined 的严格类型检查,开发者可以更有效地避免许多由于空值引发的运行时错误。同时,TypeScript 还通过非空断言运算符、枚举、bigintsymbol 等特性扩展了 JavaScript 的能力。

推荐:


在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Peter-Lu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值