Switch с Discriminated Unions

Тренажер по TypeScript для пользователей с начальным уровнем подготовки.

Тренажер по TypeScript

Использование оператора switch вместе с Discriminated Unions позволяет писать чистый и безопасный код. TypeScript анализирует каждое условие case и внутри блока автоматически сужает тип переменной до конкретного варианта.

Если вы проверили поле kind и оно равно 'cat', то внутри этого блока TypeScript разрешит доступ к методу meow(), но запретит bark(). Также это позволяет использовать проверку на исчерпываемость (exhaustiveness checking), чтобы убедиться, что обработаны все возможные варианты объединения.

Список тем

1. Результат логики switch

id: 40757_ts_switch_union_02

Проанализируйте код на 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. Доступ к недопустимому свойству

id: 40757_ts_switch_union_03

В этом фрагменте 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 сек.
Показать подсказку

3. Порядок сужения типов

id: 40757_ts_switch_union_04

Проанализируйте 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);
Расположите элементы в логичном порядке
Срабатывание ветки case 'click' — TypeScript сужает тип до ClickEvent
Вывод результата для event1 в консоль
Вызов функции processEvent с event2
Вывод результата для event2 в консоль
Вызов функции processEvent с event1
Срабатывание ветки case 'input' — TypeScript сужает тип до InputEvent
Возврат строки "Клик на координатах (10, 20)" из функции
Обработка InputEvent: доступ к свойствам value и target, формирование строки результата
Обработка ClickEvent: доступ к свойствам x и y, формирование строки результата
Создание события event2 типа 'input' со значением 'Привет' и target='username'
В функции: проверка event.type с помощью switch
Объявление Discriminated Union AppEvent, объединяющего типы ClickEvent и InputEvent
Создание события event1 типа 'click' с координатами x=10, y=20
Возврат строки "В поле username введено: Привет" из функции
Сообщения
Проверить
Показать подсказку

4. Exhaustiveness checking

id: 40757_ts_switch_union_05

В этом задании вы будете работать с 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}`);
  }
}
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

5. Конструкция switch

id: 40757_ts_switch_union_06

Из предложенных строк соберите корректную 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;
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

TypeScript: компиляция и запуск

id: 40757_compiler
TS
Запустить тренажёр (TypeScript)
НайтиКурс.Ру