Первоначально было опубликовано здесь!
Чтобы сузить свойства и методы объекта с типом 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.
Не стесняйтесь поделиться, если вы нашли это полезным 😃.