返回

类型兼容性与保护

前端


# TS系列篇|兼容性 & 保护

在TypeScript结构化的类型系统中,基本规则是:如果x要兼容y,那么y至少具有与x相同的属性。比如:这里要检查y是否能赋值给x,编译器检查x中的每个属性,看是否能在y中也找到对应属性,如果都能找到,而且类型兼容,那编译器就认为y能赋值给x,反之则认为不能赋值。

一、类型兼容性

TS的类型系统是一个结构化类型系统 ,这意味着类型兼容性是基于类型的结构来判断的,而不是基于类型的名称。例如:

interface Point {
  x: number;
  y: number;
}

interface ColoredPoint extends Point {
  color: string;
}

let p1: Point = { x: 10, y: 20 };
let p2: ColoredPoint = { x: 30, y: 40, color: 'red' };

// p2 可以赋值给 p1,因为 p2 具有与 p1 相同的属性,并且类型兼容。
p1 = p2;

在这个例子中,ColoredPointPoint的子类型,这意味着ColoredPoint具有与Point相同的所有属性,以及额外的color属性。因此,ColoredPoint变量可以赋值给Point变量。

类型兼容性还有其他几个规则,包括:

  • 协变和逆变类型 :协变类型允许子类型的值赋值给父类型变量,而逆变类型允许父类型的值赋值给子类型变量。
  • 联合类型 :联合类型允许一个变量具有多个可能的类型。例如:let x: string | number;这个变量可以存储字符串或数字。
  • 交叉类型 :交叉类型允许多个类型组合成一个新的类型。例如:type Point3D = Point & { z: number; };这个类型组合了Point类型和{ z: number; }类型。
  • 类型保护 :类型保护允许你检查一个变量的类型,并根据类型来执行不同的操作。例如:if (x is string) { ... }这个语句检查x是否是字符串,如果是,则执行语句块中的代码。
  • 类型别名 :类型别名允许你为现有类型创建一个新的名称。例如:type MyString = string;这个语句创建一个新的类型MyString,它与string类型完全相同。

二、类型的保护

TS提供了多种方法来保护类型,包括:

  • 类型注解 :类型注解可以让你为变量和函数指定类型。例如:let x: number = 10;这个语句声明了一个名为x的变量,它的类型为数字,并将其初始化为10。
  • 类型推断 :类型推断允许编译器自动推断变量和函数的类型。例如:let x = 10;这个语句声明了一个名为x的变量,它的类型为数字,但编译器会自动推断出这个类型。
  • 类型别名 :类型别名允许你为现有类型创建一个新的名称。例如:type MyString = string;这个语句创建一个新的类型MyString,它与string类型完全相同。
  • 接口 :接口允许你定义一组属性和方法,并使用它们来约束变量和函数的类型。例如:interface Point { x: number; y: number; }这个接口定义了一个名为Point的类型,它具有两个属性xy,它们的类型都是数字。
  • :类允许你创建具有属性和方法的对象。例如:class Point { x: number; y: number; }这个类创建了一个名为Point的类,它具有两个属性xy,它们的类型都是数字。
  • 枚举 :枚举允许你创建一组命名常量。例如:enum Color { Red, Green, Blue }这个枚举创建了一个名为Color的枚举,它具有三个命名常量RedGreenBlue
  • 类型保护 :类型保护允许你检查一个变量的类型,并根据类型来执行不同的操作。例如:if (x is string) { ... }这个语句检查x是否是字符串,如果是,则执行语句块中的代码。

通过使用这些技术,你可以保护代码中的类型,并确保代码的健壮性和可维护性。