Typescript:可区分类型联合模式

2023-11-29 21:24:53 浏览数 (1)

今天,让我们深入了解 TypeScript 中一个有趣的模式,它将让你大开眼界!这个模式被称为辨识类型联合或辨识联合类型。

在深入探讨这个模式之前,让我们先了解问题。

我将与大家一起编写一些代码:

代码语言:typescript复制
type PokemonState = {
  status: "Loading" | "Success" | "Error";
  pokemon?: { name: number; sprite: string; hp: number };
  error?: { message: string };
};

我创建了一个名为 PokemonState 的类型,其中包含 status、具有特定属性的 pokemon 和带有消息的 error

现在,请注意 pokemonerror 取决于 status,因此它们可以是未定义的。

  • 如果 status 是 Loading,则只返回 status
  • 如果 status 是 Success,则返回 pokemon
  • 如果 status 是 Error,则返回错误 message

让我们创建一个带有状态切换的函数:

代码语言:typescript复制
const printPokemon = (pokemonState: PokemonState) => {
  switch (pokemonState.status) {
    case "Loading":
      console.log(pokemonState.status);
      break;
    case "Success":
      console.log(pokemonState.pokemon.name, pokemonState.pokemon.sprite, pokemonState.pokemon.hp);
      break;
    case "Error":
      console.log(pokemonState.error.message);
      break;
    default:
      break;
  }
};

然而,在 TypeScript 验证中,因为可能未定义的属性,Pokemon 函数存在错误。

嘿!TypeScript 的类型安全验证在这里!就像我说的,pokemonerror 取决于 state。我们可以在函数中创建一些逻辑来验证每个状态并定义我们是否有这些属性。但这不是最好的解决方案。

现在,让我们介绍我们的模式,称为辨识类型联合。

让我们根据状态将我们的 State 重新构造为三种类型:

代码语言:typescript复制
type PokemonLoading = {
  status: "Loading";
};

type PokemonSuccessState = {
  status: "Success";
  pokemon: { name: number; sprite: string; hp: number };
};

type PokemonErrorState = {
  status: "Error";
  error: { message: string };
};

现在,我们可以在每个状态上移除 ? 可能为未定义的属性。

然后创建我们的联合类型:

代码语言:typescript复制
type PokemonNewState =
  | PokemonLoading
  | PokemonSuccessState
  | PokemonErrorState;

并且更改我们函数的参数类型:

代码语言:typescript复制
const printPokemon = (pokemonState: PokemonNewState) => {
  // Switch case 保持不变
};

现在,我们应用了辨识类型联合模式。这种模式根据一个共同的属性将类型分离,使 TypeScript 理解到它是类型安全的。

我喜欢这种模式,以及 TypeScript 如何验证和使我们的代码更清晰易懂。

就是这样!我希望你们喜欢并觉得这个 TypeScript 的提示/模式有用。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞