В этом уроке вы узнаете о Type Guard в TypeScript и сужении типов. Ограничители типов позволяют сузить тип переменной в условном блоке.
typeof
Давайте посмотрим на следующий пример:
type alphanumeric = string | number;
function add(a: alphanumeric, b: alphanumeric) {
if(typeof a === 'number' && typeof b === 'number') {
return a + b;
}
if(typeof a === 'string' && typeof b === 'string') {
return a.concat(b);
}
throw new Error('Invalid arguments. Both arguments must be either numbers or strings.');
}
Как это устроено:
- Сначала определите тип
alphanumeric, который может содержать либо строку, либо число. - Затем объявите функцию, которая добавляет две переменные
aиbс типомalphanumeric. - Затем проверьте, являются ли оба типа аргументов числами, используя оператор
typeof. Если да, то вычислить сумму аргументов с помощью оператора+. - После этого проверьте, являются ли оба типа аргументов строками, используя оператор
typeof. Если да, то соедините два аргумента. - Наконец, выдайте ошибку, если аргументы не являются ни числами, ни строками.
В этом примере TypeScript знает об использовании оператора typeof в условных блоках. Внутри следующего блока if TypeScript понимает, что a и b — это числа.
if(typeof a === 'number' && typeof b === 'number') {
return a + b;
}Точно так же в следующем блоке if TypeScript обрабатывает a и b как строки, поэтому вы можете объединить их в одну:
if(typeof a === 'string' && typeof b === 'string') {
return a.concat(b);
}
instanceof
Подобно оператору typeof, в TypeScript используется оператор instanceof.
Пример:
class Customer {
isCreditAllowed(): boolean {
// ...
return true;
}
}
class Supplier {
isInShortList(): boolean {
// ...
return true;
}
}
type BusinessPartner = Customer | Supplier;
function signContract(partner: BusinessPartner) : string {
let message: string;
if (partner instanceof Customer) {
message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
}
if (partner instanceof Supplier) {
message = partner.isInShortList() ? 'Sign a new contract the supplier' : 'Need to evaluate further';
}
return message;
}Как это устроено:
- Сначала объявите
CustomerиSupplier.
Во-вторых, создайте псевдоним типаBusinessPartner, который является типом объединенияCustomerиSupplier. - В-третьих, объявите функцию
signContract(), которая принимает параметр типаBusinessPartner. - Наконец, проверьте, является ли партнер экземпляром
CustomerилиSupplier, а затем предоставьте соответствующую логику.
Внутри следующего блока if TypeScript знает, что партнер является экземпляром типа Customer благодаря оператору instanceof :
if(partner instanceof Customer) {
message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
}Точно так же TypeScript знает, что партнер является экземпляром Supplier внутри следующего блока if :
if(partner instanceof Supplier) {
message = partner.isInShortList() ? 'Sign a new contract with the supplier' : 'Need to evaluate further';
}Когда if сужает один тип, TypeScript знает, что внутри else это не тот тип, а другой. Например:
function signContract(partner: BusinessPartner) : string {
let message: string;
if(partner instanceof Customer) {
message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
} else {
// must be Supplier
message = partner.isInShortList() ? 'Sign a new contract with the supplier' : 'Need to evaluate further';
}
return message;
}
Оператор in
Оператор in выполняет безопасную проверку существования свойства объекта. Вы также можете использовать его в качестве защиты типа. Например:
function signContract(partner: BusinessPartner) : string {
let message: string;
if('isCreditAllowed' in partner) {
message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
} else {
// must be Supplier
message = partner.isInShortList() ? 'Sign a new contract the supplier ' : 'Need to evaluate further';
}
return message;
}
Определяемые пользователем типы защиты
Определяемые пользователем охранники типа позволяют определить охрану типа или помочь TypeScript вывести тип при использовании функции.
Определяемая пользователем функция защиты типа — это функция, которая просто возвращает arg is aType. Например:
function isCustomer(partner: any): partner is Customer {
return partner instanceof Customer;
}
В этом примере isCustomer() — определяемая пользователем функция защиты типа. Теперь вы можете использовать его следующим образом:
function signContract(partner: BusinessPartner): string {
let message: string;
if(isCustomer(partner)) {
message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
} else {
message = partner.isInShortList() ? 'Sign a new contract with the supplier' : 'Need to evaluate further';
}
return message;
}
Используйте typeof и instanceof для реализации защиты типов в условных блоках.
