Как использовать оператор ‘in’ для сужения свойств и методов объекта с типом union в TypeScript?

Первоначально было опубликовано здесь!

Чтобы сузить свойства и методы объекта с типом union, мы можем использовать оператор in в TypeScript.

TL;DR

// Editor type
type Editor = {
  name: string;
};

// Admin type
type Admin = {
  name: string;
  role: string;
};

// function with parameter of user with
// union type composed of `Editor` and `Admin` type
function showRole(user: Editor | Admin) {
  // use the `in` operator to narrow down to the `Admin` type
  // since "role" property only exists in `Admin` type
  if ("role" in user) {
    console.log(user.role);
  } else {
    console.log("No user roles assigned");
  }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Например, давайте создадим тип Editor со свойством name, имеющим тип string, и другой тип Admin с name и role, имеющий тип string вот так,

// Editor type
type Editor = {
  name: string;
};

// Admin type
type Admin = {
  name: string;
  role: string;
};
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь давайте сделаем функцию showRole с параметром user с типом объединения, состоящим из типов Editor и Admin.

Это может выглядеть следующим образом,

// Editor type
type Editor = {
  name: string;
};

// Admin type
type Admin = {
  name: string;
  role: string;
};

// function with parameter of user with
// union type composed of `Editor` and `Admin` type
function showRole(user: Editor | Admin) {
  // cool code here... 🥳
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь целью приведенной выше функции должно быть отображение роли пользователя в консоли, которая будет передана в параметр функции.

Поэтому попробуем получить доступ к свойству role в переменной user.

Это можно сделать следующим образом,

// Editor type
type Editor = {
  name: string;
};

// Admin type
type Admin = {
  name: string;
  role: string;
};

// function with parameter of user with
// union type composed of `Editor` and `Admin` type
function showRole(user: Editor | Admin) {
  // this will be an error ❌ 🤯.
  console.log(user.role); // Property 'role' does not exist on type 'Editor | Admin'.
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Как только мы попытаемся получить доступ к свойству role из объектной переменной user, компилятор TypeScript выдаст ошибку Property 'role' does not exist on type 'Editor | Admin'..

Это происходит потому, что TypeScript не знает, какой тип использовать для объектной переменной user, когда мы обращаемся к свойству role. Эта ошибка вызвана тем, что объектная переменная user имеет тип объединения с типами Editor и Admin, и мы не смогли правильно определить тип, который нам нужно использовать.

  • Чтобы сузить круг до правильного типа, давайте воспользуемся оператором in. Оператор in проверяет, существует ли свойство или метод в данном объекте.

Поскольку нам нужно показать свойство role, которое присутствует только в типе Admin, мы можем использовать оператор in и проверить, существует ли свойство role в данном объекте.

Это можно сделать следующим образом,

// Editor type
type Editor = {
  name: string;
};

// Admin type
type Admin = {
  name: string;
  role: string;
};

// function with parameter of user with
// union type composed of `Editor` and `Admin` type
function showRole(user: Editor | Admin) {
  // use the `in` operator to narrow down to the `Admin` type
  // since "role" property only exists in `Admin` type
  if ("role" in user) {
    console.log(user.role);
  } else {
    console.log("No user roles assigned");
  }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь внутри блока if мы можем получить доступ ко всем свойствам и методам типа Admin, и компилятор TypeScript не покажет ошибок, чего мы и хотим. 🥳

Смотрите приведенный выше код в реальном времени в codesandbox.

Не стесняйтесь поделиться, если вы нашли это полезным 😃.


Оцените статью
devanswers.ru
Добавить комментарий