每种编程语言都是有关于数据转换的,类型级别的 TypeScript 也不例外。与其他编程语言的主要区别在于,我们的数据是类型!我们编写的程序是这样的:它以一些类型作为输入,另一些类型作为输出。
掌握这种语言需要对其不同类型的数据和数据结构的特殊性有扎实的理解。在接下来的几章中,我们将了解它们,看看它们与我们在值级别上使用的概念之间的关系,以及它们之间的区别。我们开始吧!
TypeScript 为我们提供了 5 种主要类型:原始类型、字面量类型、数据结构类型、联合类型和交叉类型。
你一定已经非常熟悉此类型。我们在日常的 TypeScript 代码里就一直使用它们来注释变量和函数。这里我们列一下原始类型:
type Primitives =
| number
| string
| boolean
| symbol
| bigint
| undefined
| null;
除了对象和函数之外的所有 JavaScript 的值都属于这个类别。其中一些原始类型是表示无限数值的归宿(如 number
或 string
),但有两类只包含一个单体:null
和 undefined
。这种特殊性使它们也成为我们第二类的一部分: 字面量类型。
字面量类型是“精确”类型,它包含单个可能的值。
type Literals =
| 20
| "Hello"
| true
| 10000n
/* | ... */;
类型为 20
的变量只能赋值给值 20
,类型为 "Hello"
的变量只能赋值给值 "Hello"
,等等。
const twenty: 20 = 20; // ✅ works!
const hundred: 20 = 100;
// ^ ❌ `100` isn't assignable to the type `20`.
有无数的字面量类型,它们看起来就像常规的值,但请别搞错:它们就是类型!
值和类型分属两个不同的世界ーー它们独立存在,无法在单个表达式中将它们混在一起$^{1}$。我发现将字面量类型视为类型世界中值的一种反射是有帮助的,但是我们需要记住它们是完全不同的东西。一个显著的区别是,我们不能在类型级别代码中编写算术表达式。例如,即使 const five = 2 + 3
完全有效,type five = 2 + 3
也不会起任何作用。
当将字面量类型放在一起来描述变量时,立马变得特别管用,因为这些变量只能包含一组有限可能的值,比如类型 type TrafficLight = "green" | "orange" | "red"
。
在我们的类型世界中,我们有四种内置的数据结构可以使用:对象、记录、元组和数组。
type DataStructures =
| { key1: boolean; key2: number } // objects
| { [key: string]: number } // records
| [boolean, number] // tuples
| number[]; // arrays