Уроки модуля (1/2)
Тип Охранники
Сужение типов — одна из наиболее важных концепций TypeScript. Однако зачастую стандартных средств защиты типов, таких как typeof или instanceof, недостаточно для сложных пользовательских объектов. Здесь на помощь приходят Защитники пользовательского типа.
Стандартный тип защиты
Начнем с подведения итогов того, как TypeScript сужает типы с помощью стандартных операторов JavaScript:
function processInput(val: string | number) {
if (typeof val === 'string') {
// Here 'val' is of type string
console.log(val.toUpperCase());
} else {
// Here 'val' is of type number
console.log(val.toFixed(2));
}
}Пользовательские типы защиты (оператор is)
Чтобы определить защиту пользовательского типа, мы создаем функцию, которая возвращает предикат типа в формате parameterName is Type вместо стандартного логического возвращаемого типа.
Функция должна возвращать логическое значение (true или false). Если он возвращает true, TypeScript будет знать, что переданный параметр имеет указанный тип.
interface Cat {
name: string;
meow(): void;
}
interface Dog {
name: string;
bark(): void;
}
// This is a custom type guard
function isCat(animal: Cat | Dog): animal is Cat {
return (animal as Cat).meow !== undefined;
}
function makeNoise(pet: Cat | Dog) {
if (isCat(pet)) {
// Here TypeScript knows 'pet' is a Cat
pet.meow();
} else {
// Here TypeScript knows 'pet' is a Dog
pet.bark();
}
}Безопасность и литье (as против типовых ограждений)
Приведение типов (например, val as Cat) заставляет компилятор доверять разработчику без какой-либо реальной проверки во время выполнения. Если объект времени выполнения не соответствует ожиданиям, код автоматически выдаст ошибку или выдаст исключения.
С другой стороны, специальные средства защиты типов выполняют надежную и динамическую проверку во время выполнения, безопасно и точно информируя компилятор TypeScript о фактическом типе переменной:
function processInput(input: unknown) {
// unsafe casting: could crash if input does not have the split method
// const str = input as string;
// console.log(str.split(' '));
// safe guard
if (isString(input)) {
console.log(input.split(' ')); // 100% Safe!
}
}Попробуйте сами
Упражнение 1: Защита струнного типа
Создайте простую функцию с именем isString, которая действует как защита пользовательского типа и проверяет, является ли неизвестное значение строкой.
Показать подсказку
Тип возвращаемого значения функции должен быть val — строка, и вам следует использовать typeof, чтобы проверить, равен ли он «строке».
Решение доступно после 3 попыток
Упражнение 2. Защита типов премиум-пользователей
Учитывая типы User и PremiumUser, напишите функцию защиты типа isPremiumUser(user: User): user is PremiumUser, которая проверяет, имеет ли пользователь роль «премиум».
Показать подсказку
Определите подпись как функцию isPremiumUser(user: User): пользователь — PremiumUser и сравните user.role с «premium».
Решение доступно после 3 попыток
Упражнение 3. Проверка пользовательского объекта ошибки
Реализуйте функцию isCustomError(err:known): err — это функция CustomError, которая проверяет, является ли неизвестное значение ненулевым объектом CustomError, содержащим ключ «code».
Показать подсказку
Сначала проверьте, является ли typeof err «объектом», а не нулевым, затем используйте оператор «in», чтобы проверить свойство «code».
Решение доступно после 3 попыток
Упражнение 4. Защита типа администратора
Имея два интерфейса User (со свойством role: string) и Admin (расширяющим User и имеющим свойство adminToken: string), напишите функцию защиты типа с именем isAdmin, которая принимает пользователя типа User и возвращает предикат типа user — Admin. Охранник должен проверить, равна ли роль пользователя «admin».
Показать подсказку
Определите подпись как функцию isAdmin(user: User): пользователь является администратором и проверьте, имеет ли user.role === 'admin'.
Решение доступно после 3 попыток