DevGang
Авторизоваться

Typescript: шаблон объединения разных типов

Давайте поговорим об одном интересном шаблоне в Typescript, этот шаблон называется Discriminated Type Union или Discriminated Union Type. Прежде чем мы углубимся в эту тему, нам нужно понять проблему. Я напишу с вами код:

type PokemonState = {
  status: "Loading" | "Success" | "Error";
  pokemon?: { name: number; sprite: string; hp: number };
  error?: { message: string };
};

Я создал тип под названием PokemonState, который содержит statuspokemon с некоторыми свойствами и error сообщением.

Теперь заметьте, что pokemon и error, зависит от статуса, поэтому может быть undefined.

Если статус Loading, просто верните статус.
Если статус Success, просто верните покемона.
Если статус Error, просто верните сообщение об ошибке.

Итак, давайте создадим функцию с включенным состоянием:

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;
  }
};

Но я покажу то, что вижу в VSCode с проверкой Typescript:

Проверка безопасности типов Typescript уже здесь! Как я сказал, pokemon и error зависит от state. Мы можем создать некоторую логику для нашей функции, проверяющую каждый статус, и определять, есть ли у нас наши свойства. Но это не лучшее решение.

Но теперь входит шаблон, называемый Dicriminated Type Union. Давайте переделаем наш тип State на три типа на основе нашего состояния.

type PokemonLoading = {
  status: "Loading";
};

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

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

Теперь мы можем удалить ? cвойство может быть undefined для каждого состояния. И давайте создадим наш тип объединения:

type PokemonNewState =
  | PokemonLoading
  | PokemonSuccessState
  | PokemonErrorState;

И изменим тип параметра нашей функции:

const printPokemon = (pokemonState: PokemonNewState) => {
  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 безопасным для типов.

Мне нравится этот шаблон, и я просто поражаюсь тому, как Typescript может проверить и сделать наш код более чистым и понятным.

Источник:

#JavaScript #TypeScript
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу