TypeScript 系列 - TypeScript 的类型系统

58 阅读4分钟

基本类型

object 类型

根据 JavaScript 的设计,object 类型包含了所有对象、数组和函数。

const x:object = { foo: 123 };
const y:object = [1, 2, 3];
const z:object = (n:number) => n + 1;

undefined 类型,null 类型

如果没有声明类型的变量,被赋值为undefinednull,它们的类型会被推断为any

如果希望避免这种情况,则需要打开编译选项strictNullChecks

包装对象类型

包装对象的概念

String()只有当作构造函数使用时(即带有new命令调用),才会返回包装对象。

包装对象类型与字面量类型

为了区分这两种情况,TypeScript 对五种原始类型分别提供了大写和小写两种类型。 建议只使用小写类型,不使用大写类型。

  • Boolean 和 boolean
  • String 和 string
  • Number 和 number
  • BigInt 和 bigint
  • Symbol 和 symbol

Object 类型与 object 类型

TypeScript 的对象类型也有大写Object和小写object两种。

Object 类型

除了undefinednull这两个值不能转为对象,其他任何值都可以赋值给Object类型。

空对象{}Object类型的简写形式

object 类型

小写的object类型代表 JavaScript 里面的狭义对象,即可以用字面量表示的对象,只包含对象、数组和函数,不包括原始类型的值。

建议总是使用小写类型object,不使用大写类型Object

无论是大写的Object类型,还是小写的object类型,都只包含 JavaScript 内置对象原生的属性和方法,用户自定义的属性和方法都不存在于这两个类型之中。

undefined 和 null 的特殊性

undefinednull既是值,又是类型。

作为值,它们有一个特殊的地方:任何其他类型的变量都可以赋值为undefinednull

strictNullChecks。只要打开这个选项,undefinednull就不能赋值给其他类型的变量(除了any类型和unknown类型)。

值类型

TypeScript 规定,单个值也是一种类型,称为“值类型”。

TypeScript 推断类型时,遇到const命令声明的变量,如果代码里面没有注明类型,就会推断该变量是值类型。

const命令声明的变量,如果赋值为对象,并不会推断为值类型。

父类型不能赋值给子类型,所以报错了。

但是,反过来是可以的,子类型可以赋值给父类型。类型断言

联合类型

联合类型(union types)指的是多个类型组成的一个新类型,使用符号|表示。

联合类型A|B表示,任何一个类型只要属于AB,就属于联合类型A|B

如果某个变量确实可能包含空值,就可以采用联合类型的写法。

“类型缩小”是 TypeScript 处理联合类型的标准方法,凡是遇到可能为多种类型的场合,都需要先缩小类型,再进行处理。

交叉类型

交叉类型(intersection types)指的多个类型组成的一个新类型,使用符号&表示。

交叉类型A&B表示,任何一个类型必须同时属于AB,才属于交叉类型A&B,即交叉类型同时满足AB的特征。

交叉类型的主要用途是表示对象的合成。

交叉类型常常用来为对象类型添加新属性。

type A = { foo: number };

type B = A & { bar: number };

type 命令

type命令用来定义一个类型的别名。 别名的作用域是块级作用域 别名支持使用表达式,也可以在定义一个别名时,使用另一个别名,即别名允许嵌套。

type World = "world";
type Greeting = `hello ${World}`;

typeof 运算符

TypeScript 将typeof运算符移植到了类型运算,它的操作数依然是一个值,但是返回的不是字符串,而是该值的 TypeScript 类型。

所以TypeScript 规定,typeof 的参数只能是标识符,不能是需要运算的表达式。 typeof命令的参数不能是类型。

type Age = number;
type MyAge = typeof Age; // 报错

类型的兼容

如果类型A的值可以赋值给类型B,那么类型A就称为类型B的子类型(subtype)