Уроки модуля (2/2)
Союзы и сужение
В реальном мире переменные и ответы API не всегда имеют один фиксированный тип. TypeScript предлагает Объединенные типы для обработки изменчивости и Сужение типов для безопасной работы с ними во время выполнения.
Типы союзов
Тип объединения позволяет переменной принимать значения разных типов. Это выражается с помощью символа вертикальной черты (|):
let result: number | string;
result = 42; // Valid
result = 'Error 404'; // ValidОднако при работе с типом объединения мы не можем напрямую вызывать методы, принадлежащие только одному из типов (например, мы не можем вызвать .toUpperCase(), если переменная также может быть number). Надо сначала «сузить» тип.
Тип Сужение
Сужение типа — это процесс, в котором TypeScript анализирует структуры потока управления (например, if или switch), чтобы определить более конкретный тип переменной во время выполнения.
Существует несколько способов выполнения сужения:
1. Оператор typeof
Идеально подходит для различения примитивных типов:
function printLength(value: string | number) {
if (typeof value === 'string') {
// TypeScript knows 'value' is a string here
console.log(value.length);
} else {
// TypeScript knows 'value' is a number here
console.log(value.toFixed(2));
}
}2. Оператор in
Используется для проверки наличия определенного свойства у объекта:
interface Fish {
swim: () => void;
}
interface Bird {
fly: () => void;
}
function move(animal: Fish | Bird) {
if ('swim' in animal) {
animal.swim(); // Narrowing to Fish
} else {
animal.fly(); // Narrowing to Bird
}
}Дискриминированные профсоюзы
Шаблон Дискриминированные объединения заключается в создании объектов, имеющих общее свойство с уникальным литеральным значением (называемым дискриминатором). TypeScript распознает этот дискриминатор и автоматически сужает тип в условных блоках.
interface SuccessResponse {
status: 'success'; // Literal discriminator
data: string;
}
interface ErrorResponse {
status: 'error'; // Literal discriminator
errorMessage: string;
}
type ApiResponse = SuccessResponse | ErrorResponse;
function handleResponse(response: ApiResponse) {
if (response.status === 'success') {
console.log('Data received:', response.data);
} else {
console.error('An error occurred:', response.errorMessage);
}
}Попробуйте сами
Упражнение 1. Типы объединений
Объявите переменную с именем id, которая может быть числом или строкой. Сначала инициализируйте его номером 101, затем присвойте строковое значение «USER-101».
Показать подсказку
Используйте | оператор для объединения числа и строки в объявлении переменной let.
Решение доступно после 3 попыток
Упражнение 2. Сужение базового типа
Создайте функцию с именем formatInput, которая принимает входной параметр типа строки или числа. Если ввод является строкой, верните ввод, преобразованный в верхний регистр. Если это число, верните входные данные, умноженные на 2. Укажите типы явно.
Показать подсказку
Используйте typeof input === 'string' внутри блока if для разветвления поведения.
Решение доступно после 3 попыток
Упражнение 3: Сужение с помощью «in»
Учитывая два интерфейса Car (с методом Drive) и Boat (с методом Sail), напишите функцию с именем moveVehicle, которая принимает параметр транспортного средства типа Car или Boat. Если транспортное средство имеет свойство привода, выполните метод привода(). В противном случае выполните метод парус().
Показать подсказку
Используйте оператор in в форме «ездить» в автомобиле, чтобы сузить интерфейс.
Решение доступно после 3 попыток
Упражнение 4. Форма распознанного объединения
Определите тип Shape, который представляет собой объединение двух типов: Circle и Square. У круга есть свойство вида, для которого установлено значение «круг» (буквальное значение) и радиус (число). У Square есть свойство kind, для которого установлено значение «square» (буквальное значение) и сторона (число). Затем напишите функцию getArea, которая принимает форму типа Shape и возвращает площадь в виде числа (для круга Math.PI * радиус * радиус, для стороны квадрата * сторона).
Показать подсказку
Используйте shape.kind === 'circle' внутри getArea, чтобы распознать тип и вычислить правильную площадь.
Решение доступно после 3 попыток