「TypeScript」类型守卫(TypeGuard)🍃

一、简介

 TypeScript中的类型守卫(Type Guards)是一种技术,它可以用于在代码中更明确地指定变量的类型。这是TypeScript提供的一种强大功能,因为它可以帮助开发者避免类型错误,同时还能利用TypeScript的类型系统来提供更好的代码智能提示和自动补全。类型守卫主要用于告诉TypeScript编译器,某个变量在特定的代码块中是特定的类型。

二、使用场景

 类型守卫一般要配合if语句,在if语句创建的块级作用域中收窄对应变量的类型。当然也可以使用三目运算符、逻辑与运算符等使用。

1. 区分联合类型

typescript 复制代码
function process(input: string | number) {
  if (typeof input === "string") {
    // do something...
  } else {
    // do something...
  }
}

2. 收窄类型

typescript 复制代码
function move(animal: Animal) {
  if (animal instanceof Bird) {
    animal.fly();
  } else if (animal instanceof Fish) {
    animal.swim();
  } else {
    // do something...
  }
}

3. 处理未知类型

typescript 复制代码
function move(animal: unknown) {
  // do something...
}

三、写法

1. "instanceof " 操作符

 当你想要检查一个对象是否是某个类的实例时,可以使用instanceof。

typescript 复制代码
abstract class Animal {
  abstract makeSound(): void;
}

abstract class Fish extends Animal {
  abstract swim(): void;
}

abstract class Bird extends Animal {
  abstract fly(): void;
}

class Shark extends Fish {
  makeSound() {
    console.log("Shark make sound");
  }

  swim() {
    console.log("Shark swim");
  }
}

class Eagle extends Bird {
  makeSound() {
    console.log("Eagle make sound");
  }

  fly() {
    console.log("Eagle fly");
  }
}

function getMovement(animal: Animal) {
  if (animal instanceof Fish) {
    // 在这个作用域(if创建的作用域)中,animal 被收窄为 Fish
    return animal.swim();
  }

  if (animal instanceof Bird) {
    // 在这个作用域(if创建的作用域)中,animal 被收窄为 Bird
    return animal.fly();
  }
}

2. "in" 操作符

 这种方式主要用于检查一个具有特定属性的对象。

typescript 复制代码
abstract class Animal {
  abstract makeSound(): void;
}

abstract class Fish extends Animal {
  abstract swim(): void;
}

abstract class Bird extends Animal {
  abstract fly(): void;
}

class Shark extends Fish {
  makeSound() {
    console.log("Shark make sound");
  }

  swim() {
    console.log("Shark swim");
  }
}

class Eagle extends Bird {
  makeSound() {
    console.log("Eagle make sound");
  }

  fly() {
    console.log("Eagle fly");
  }
}

function getMovement2(animal: Animal) {
  if ("swim" in animal) {
    return animal.swim();
  }

  if ("fly" in animal) {
    return animal.fly();
  }
}

3. 自定义类型守卫

 在复杂的应用中,可能需要基于特定逻辑来确定变量的类型,此时可以创建自定义的类型守卫。通过类型谓词"is" 实现变量类型的收窄。

typescript 复制代码
abstract class Animal {
  abstract makeSound(): void;
}

abstract class Fish extends Animal {
  abstract swim(): void;
}

abstract class Bird extends Animal {
  abstract fly(): void;
}

class Shark extends Fish {
  makeSound() {
    console.log("Shark make sound");
  }

  swim() {
    console.log("Shark swim");
  }
}

class Eagle extends Bird {
  makeSound() {
    console.log("Eagle make sound");
  }

  fly() {
    console.log("Eagle fly");
  }
}

function isAccurateAnimal<T extends Animal>(
  animal: unknown,
  type: abstract new (...args: any[]) => T
): animal is T {
  return animal instanceof type;
}

function getMovement(animal: Animal) {
  if (isAccurateAnimal(animal, Fish)) {
    animal.swim();
  }

  if (isAccurateAnimal(animal, Bird)) {
    animal.fly();
  }
}

 自定义类型守卫传入需要收窄类型的变量,并定义相应的收窄类型,返回布尔值的结果,当结果为真则变量的类型收窄为定义的类型,反之不进行收窄。

typescript 复制代码
function narrowType(object: unknown): object is [NarrowedType] {
  return [condition]
}
相关推荐
行者全栈架构师1 小时前
我让 AI 独立开发了一款游戏:零依赖、188 个测试全绿、工期压到四分之一
typescript·canvas·vibecoding
Eyfcom2 小时前
〖深度〗鸿蒙 ArkTS 移动应用开发经验:从 TypeScript 心智模型到声明式运行时的六层认知重构
typescript·移动开发·harmonyos·arkts
Patrick_Wilson1 天前
悬浮提示从哪来:LSP、tsserver 与 .d.ts
typescript·npm·前端工程化
oldnicke2 天前
理解 TRAE 的 Agent + IDE 思路:用一个 Markdown 检查器拆解完整交付
typescript
钱栈up2 天前
GitHub 热榜实测|REA:用 Agent 逆向一切
typescript·开源·github
keyipatience2 天前
TypeScript学习(1)
前端·javascript·学习·typescript·html·css3
RuoyiOffice2 天前
Vue3+TypeScript 企业管理平台统一UI:新增一个模块,为什么还要重新调样式?
spring boot·typescript·vue3·组件化开发·企业管理软件·ruoyi office·统一ui
Shockang3 天前
TanStack Router 实战:URL 校验、Loader 与路由权限
typescript·react·路由·前端开发·tanstack router
TYC93 天前
Mac创建Vue3+TypeScript或者React+TypeScript项目
前端·javascript·typescript
fbincon4 天前
Claude Code 自定义状态栏工具:安装、配置与 Subagent 状态展示
python·typescript·claude·claude-code·statusline