Использование оператора switch вместе с Discriminated Unions позволяет писать чистый и безопасный код. TypeScript анализирует каждое условие case и внутри блока автоматически сужает тип переменной до конкретного варианта.
Если вы проверили поле kind и оно равно 'cat', то внутри этого блока TypeScript разрешит доступ к методу meow(), но запретит bark(). Также это позволяет использовать проверку на исчерпываемость (exhaustiveness checking), чтобы убедиться, что обработаны все возможные варианты объединения.
- Модуль 1: Введение в TypeScript
- Модуль 2: Примитивные типы
- Модуль 3: Специальные типы
- Модуль 4: Массивы
- Модуль 5: Кортежи (Tuples)
- Модуль 6: Объекты
- Модуль 7: Функции
- Модуль 8: Union типы
- Модуль 9: Литеральные типы
- Модуль 10: Type Aliases
- Модуль 11: Интерфейсы
- Модуль 12: Type Guards и Narrowing
- Модуль 13: Enums
- Модуль 14: Классы
- Модуль 15: Generics — основы
- Модуль 16: Generics — ограничения
- Модуль 17: Utility Types — базовые
- Модуль 18: Utility Types — работа с Union
- Модуль 19: Utility Types — функции
- Модуль 20: Type Assertions
- Модуль 21: Keyof и Typeof операторы
- Модуль 22: Mapped Types
- Модуль 23: Conditional Types
- Модуль 24: Discriminated Unions
- Паттерн Discriminated Union.
- Exhaustiveness checking.
- Switch с Discriminated Unions.
- Модуль 25: Модули и типы
- Модуль 26: Declaration Files
- Модуль 27: Типизация асинхронного кода
- Модуль 28: Практические паттерны
1. Результат логики switch
Проанализируйте код на TypeScript, использующий discriminated union и оператор switch. Определите, какая строка будет выведена в консоль при выполнении этого кода. Обратите внимание на тип переданного объекта и соответствующий case в switch.
type Dog = { kind: 'dog'; bark: string };
type Cat = { kind: 'cat'; meow: string };
type Bird = { kind: 'bird'; tweet: string };
type Animal = Dog | Cat | Bird;
function animalSound(animal: Animal): string {
switch (animal.kind) {
case 'dog':
return animal.bark;
case 'cat':
return animal.meow;
case 'bird':
return animal.tweet;
default:
return 'Unknown animal';
}
}
const myPet: Animal = { kind: 'cat', meow: 'Meow!' };
console.log(animalSound(myPet));2. Доступ к недопустимому свойству
В этом фрагменте TypeScript-кода используется discriminated union для представления геометрических фигур. Внутри оператора switch в одном из блоков case происходит попытка обратиться к свойству, которое не существует у данного типа объединения. Найдите и исправьте строку с ошибкой, чтобы код корректно вычислял площадь фигуры.
type Shape = | { kind: 'circle'; radius: number } | { kind: 'square'; side: number }; function getArea(shape: Shape): number { switch (shape.kind) { case 'circle': return Math.PI * shape.radius * shape.radius; case 'square': return shape.radius * shape.radius; // Ошибка здесь }}3. Порядок сужения типов
Проанализируйте TypeScript-код сверху и восстановите последовательность логических шагов выполнения программы. Шаги снизу перемешаны — расставьте их в правильном порядке, чтобы отразить, как программа обрабатывает события разных типов с использованием Discriminated Unions и switch.
type ClickEvent = { type: 'click'; x: number; y: number };
type InputEvent = { type: 'input'; value: string; target: string };
type AppEvent = ClickEvent | InputEvent;
function processEvent(event: AppEvent): string {
switch (event.type) {
case 'click':
return `Клик на координатах (${event.x}, ${event.y})`;
case 'input':
return `В поле ${event.target} введено: ${event.value}`;
default:
const _exhaustiveCheck: never = event;
return _exhaustiveCheck;
}
}
// Входные данные
const event1: AppEvent = { type: 'click', x: 10, y: 20 };
const event2: AppEvent = { type: 'input', value: 'Привет', target: 'username' };
const result1 = processEvent(event1);
const result2 = processEvent(event2);
console.log(result1);
console.log(result2);4. Exhaustiveness checking
В этом задании вы будете работать с discriminated unions (размеченные объединения) в TypeScript и практиковать технику исчерпывающей проверки (exhaustiveness checking) в конструкции switch. Вам нужно дополнить код так, чтобы TypeScript мог статически проверить, что все возможные варианты объединения обработаны. Для этого в блоке default используется переменная, которой присваивается значение параметра. Ваша задача — указать правильный тип для этой переменной, чтобы обеспечить проверку исчерпываемости. После заполнения пропусков код должен корректно компилироваться и выполнять логику обработки всех вариантов объединения.
type Shape = Circle | Square;
interface Circle {
kind: 'circle';
radius: number;
}
interface Square {
kind: 'square';
sideLength: number;
}
function getArea(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2;
case 'square':
return shape.sideLength ** 2;
default:
// Для проверки исчерпываемости присваиваем значение переменной с типом never
const exhaustiveCheck: input1S = shape;
throw new Error(`Неизвестная фигура: ${exhaustiveCheck}`);
}
}5. Конструкция switch
Из предложенных строк соберите корректную typescript-функцию getArea, которая вычисляет площадь фигуры (Shape) с использованием discriminated union и конструкции switch. Функция должна корректно обрабатывать варианты 'circle' и 'square' и выполнять исчерпывающую проверку (exhaustive check) в default. Лишние строки (break, case для несуществующего варианта) в решение включать не следует.
function getArea(shape: Shape): number { switch (shape.kind) { case 'circle': return Math.PI * shape.radius ** 2; case 'square': return shape.sideLength ** 2; default: const _exhaustiveCheck: never = shape; return _exhaustiveCheck; }} break; case 'triangle': return 0;