头图

小册

这是我整理的学习资料,非常系统和完善,欢迎一起学习

类型系统层级

TypeScript 的类型系统是强类型和静态类型的,这为开发者提供了强大的类型检查和类型安全保障,同时也增加了一定的学习复杂性。为了更好地理解 TypeScript 的类型系统,本文将全面介绍其类型系统层级,包括顶层类型(Top Type)和底层类型(Bottom Type),以及在这个层次结构中如何处理和操作各种类型。理解 TypeScript 的类型系统层级有助于我们更好地使用和掌握 TypeScript,写出更健壮、可维护的代码。

1. 顶层类型(Top Type)

顶层类型是所有其他类型的父类型,这意味着在 TypeScript 中的任何类型都可以看作是顶层类型的子类型。TypeScript 中有两个特殊的顶层类型:anyunknown

1.1 any 类型

any类型是 TypeScript 的一个逃生窗口,它可以接受任意类型的值,并且对 any 类型的值进行的任何操作都是允许的。使用 any 类型,可以使我们绕过 TypeScript 的类型检查。下面的例子展示了 any 类型的灵活性:

let a: any = 123;  // OK
a = 'hello';  // OK
a = true;  // OK
a = { id: 1, name: 'Tom' }; // OK

a.foo();  // OK

我们可以看到,我们可以将任何类型的值赋给 any 类型的变量,甚至可以对 any 类型的值进行我们想要的任何操作,而 TypeScript 编译器并不会对此做出任何投诉。然而,正是由于其超高的灵活性,使得 any 类型在一定程度上削弱了 TypeScript 的类型安全性,因此在我们编写 TypeScript 代码时,应尽量避免使用 any 类型。

1.2 unknown 类型

unknown 类型与 any 类型在接受任何类型的值这一点上是一样的,但 unknown 类型却不能像 any 类型那样对其进行任何操作。我们在对 unknown 类型的值进行操作之前,必须进行类型检查或类型断言,确保操作的安全性。

let u: unknown = 123;  // OK
u = 'hello';  // OK
u = true;  // OK
u = { id: 1, name: 'Tom' }; // OK

// Error: Object is of type 'unknown'.
// u.foo(); 

if (typeof u === 'object' && u !== null) {
  // OK after type check
  console.log((u as { id: number,

 name: string }).name);
}

在这个例子中,我们对 unknown 类型的值 u 进行了类型检查,然后通过类型断言安全地访问了其 name 属性。

2. 底层类型(Bottom Type)

与顶层类型相对,底层类型是所有类型的子类型。这意味着,在类型系统的层次结构中,任何类型都可以被看作是底层类型的超类型。在 TypeScript 中,never 类型是唯一的底层类型。

never 类型用来表示永远不可能存在的值的类型。比如,一个永远抛出错误或者永远处于死循环的函数的返回类型就是 never

function error(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) {}
}

在上面的代码中,函数 errorinfiniteLoop 的返回类型都是 never,这是因为这两个函数都永远不会有返回值。

3. 对比:顶层类型 vs 底层类型

顶层类型和底层类型是 TypeScript 类型系统的两个重要组成部分,它们各自扮演着不同的角色。

顶层类型 anyunknown 能够接受任何类型的值,这使得我们可以灵活地处理不确定类型的数据。然而,any 类型和 unknown 类型在使用上有着重要的区别:any 类型允许我们对其进行任何操作,而 unknown 类型则要求我们在操作之前进行类型检查或类型断言,以确保类型的安全性。

底层类型 never 有点特殊,它表示一个永远不会有值的类型。在实际开发中,我们可能很少直接使用 never 类型,但是它在 TypeScript 的类型推断和控制流分析中起着非常重要的作用。

  • 理解 TypeScript 的类型系统层级有助于我们编写更健壮、可维护的 TypeScript 代码。尽管 any 类型提供了很大的灵活性,但是它的滥用可能会削弱 TypeScript 的类型安全性。因此,我们应尽量避免使用 any 类型,而优先使用 unknown 类型和类型断言、类型保护等方式来处理不确定类型的数据。
  • 同时,虽然我们可能很少直接使用 never 类型,但是理解它的含义和用法,对于我们理解 TypeScript 的类型推断和控制流分析也是非常有帮助的。

linwu
41 声望11 粉丝

☀高级前端开发工程师