TypeScript 类型保护

类型保护是 TypeScript 中的一项强大功能,它允许开发人员执行运行时检查以缩小变量的类型范围。这可确保更精确的类型信息,从而产生更安全、更可预测的代码。本文探讨了什么是类型保护以及如何有效地使用它们。

什么是类型保护?

类型保护是执行运行时检查的表达式,允许 TypeScript 推断变量的更具体类型。它们有助于区分不同类型,尤其是在处理联合类型时。类型保护可以使用各种技术实现,包括:

  • 用户定义类型谓词
  • 类型断言
  • 实例检查
  • 使用 typeof 运算符
  • 使用 in 运算符

用户定义类型谓词

用户定义类型谓词是返回布尔值的函数,具有特殊的返回类型,用于指示被检查变量的类型。创建和使用它们的方法如下:

function isString(value: any): value is string {
  return typeof value === 'string';
}

function printString(value: any) {
  if (isString(value)) {
    console.log(value.toUpperCase()); // TypeScript knows value is a string here
  } else {
    console.log('Not a string');
  }
}

在上面的例子中,isString 是一个用户定义的类型谓词,它可以帮助 TypeScript 理解 valueif 块内的字符串。

类型断言

类型断言告诉 TypeScript 将变量视为特定类型。此方法不会执行运行时检查,但会将类型告知 TypeScript 编译器。例如:

function printLength(value: any) {
  console.log((value as string).length); // Assert value is a string
}

在这个例子中,value as string 告诉 TypeScript 假设 value 是一个字符串,而无需执行运行时检查。

实例检查

实例检查用于确定对象是否是特定类的实例。这对于在使用类时缩小类型范围很有用:

class Dog {
  bark() { console.log('Woof'); }
}

class Cat {
  meow() { console.log('Meow'); }
}

function speak(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    animal.bark(); // TypeScript knows animal is a Dog here
  } else {
    animal.meow(); // TypeScript knows animal is a Cat here
  }
}

在这个例子中,instanceof 运算符帮助 TypeScript 根据其类推断 animal 的类型。

使用 typeof 运算符

typeof 运算符可用于检查原始类型,例如 stringnumberboolean

function processValue(value: string | number) {
  if (typeof value === 'string') {
    console.log(value.toUpperCase()); // TypeScript knows value is a string here
  } else {
    console.log(value.toFixed(2)); // TypeScript knows value is a number here
  }
}

这里,typeof 用于检查value 是否是 string 还是 number,并相应地缩小类型。

使用 in 运算符

in 运算符检查对象中是否存在属性。这对于区分具有共同属性的类型很有用:

interface Bird {
  fly: () => void;
}

interface Fish {
  swim: () => void;
}

function move(creature: Bird | Fish) {
  if ('fly' in creature) {
    creature.fly(); // TypeScript knows creature is a Bird here
  } else {
    creature.swim(); // TypeScript knows creature is a Fish here
  }
}

在这个例子中,in 运算符帮助 TypeScript 根据方法的存在来确定 creatureBird 还是 Fish

结论

TypeScript 类型保护是灵活安全地处理类型的必备工具。它们允许更精确地进行类型检查,并通过确保在不同场景中使用正确的类型来防止运行时错误。理解和有效使用类型保护可以产生更强大且更易于维护的 TypeScript 代码。