В этом уроке вы узнаете о 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
для реализации защиты типов в условных блоках.