Паттерн Discriminated Union

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

Тренажер по TypeScript

Паттерн Discriminated Union (размеченное объединение) — это ключевой инструмент для работы со сложными структурами данных в TypeScript. Он позволяет создать тип, который может принимать одну из нескольких форм, при этом каждая форма имеет уникальное общее поле — дискриминант (обычно kind, type или tag).

Благодаря этому полю, TypeScript точно знает, с каким именно интерфейсом вы работаете в данный момент, и подсказывает только доступные для него свойства. Это делает код надежным и избавляет от множества проверок типов вручную.

Список тем

1. Поиск дискриминанта

id: 40755_ts_discrim_union_01

Перед вами два интерфейса TypeScript. Ваша задача — найти и отметить свойство, которое является общим дискриминантом для обоих интерфейсов. Дискриминант — это общее поле с литеральным типом, которое позволяет различать типы в размеченном объединении. Кликните на свойство (включая его имя и тип), которое выполняет эту роль в каждом интерфейсе. Не отмечайте другие свойства, которые не являются общими или не имеют литерального типа.

Кликните по всем фрагментам, которые подходят под условие задания.
interface Circle {
  {{kind: "circle"~|~t1}};
  {{radius: number~|~t2}};
}

interface Square {
  {{kind: "square"~|~t3}};
  {{sideLength: number~|~t4}};
}
Сообщения
Проверить
Показать подсказку

2. Добавление тега

id: 40755_ts_discrim_union_02

В этом задании вам нужно дополнить определение интерфейса для паттерна Discriminated Union в TypeScript. В предоставленном коде не хватает поля-дискриминанта, которое позволяет различать типы в объединении. Впишите в указанные места название этого поля (например, type или kind) и соответствующее ему литеральное строковое значение, чтобы код стал корректным и тип Shape мог использоваться как дискриминированное объединение.

Заполните пропуски
interface Circle {
    input1S: input2S;
    radius: number;
}

interface Square {
    kind: 'square';
    sideLength: number;
}

type Shape = Circle | Square;

function getArea(shape: Shape): number {
    if (shape.kind === 'circle') {
        return Math.PI * shape.radius * shape.radius;
    } else {
        return shape.sideLength * shape.sideLength;
    }
}
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

3. Выбор правильного литерала

id: 40755_ts_discrim_union_03

В этом задании вы отработаете использование discriminated unions в TypeScript. Ниже приведён код, определяющий объединённый тип Shape, который может быть либо Circle, либо Square. Создаются два объекта shape1 и shape2, но в них пропущены значения для поля `kind`. Ваша задача — выбрать из выпадающего списка правильные строковые литералы для `kind` в каждом объекте, чтобы они соответствовали остальным свойствам (radius для круга, sideLength для квадрата). Это упражнение поможет закрепить понимание того, как общее поле-дискриминант позволяет TypeScript различать типы в объединении.

Нужно правильно расставить в пропуски предложенные варианты
type Shape = Circle | Square;

interface Circle {
    kind: "circle";
    radius: number;
}

interface Square {
    kind: "square";
    sideLength: number;
}

const shape1: Shape = {
    kind: input1S,
    radius: 10
};

const shape2: Shape = {
    kind: input2S,
    sideLength: 4
};
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

4. Сопоставление типа и свойства

id: 40755_ts_discrim_union_04

В этом задании вам нужно сопоставить значения дискриминанта (типы фигур) из discriminated union в TypeScript с уникальными свойствами, которые определены для каждого типа. В левой колонке приведены названия типов фигур, используемые как значения общего поля-дискриминанта, а в правой — их уникальные свойства. Сопоставьте каждый тип с соответствующими свойствами, обращая внимание на характерные для каждой фигуры атрибуты.

Сопоставьте строки в правой(нижней) части с соответствующими строками в левой(верхней) по порядковому номеру
circle
square
rectangle
triangle
side
radius
width, height
base, height
Сообщения
Проверить
Показать подсказку

5. Ошибка в типе дискриминанта

id: 40755_ts_discrim_union_05

В этом фрагменте кода TypeScript используется паттерн Discriminated Union для различения типов фигур. Однако в объявлении одного из типов допущена ошибка: поле-дискриминант имеет тип `string` вместо конкретного строкового литерала, что нарушает работу паттерна. Найдите и исправьте эту строку, чтобы TypeScript мог корректно сужать типы.

Найдите ошибку и исправьте
type Circle = {
  type: string;
  radius: number;
};
 
type Square = {
  type: "square";
  sideLength: number;
};
 
type Shape = Circle | Square;
 
function getArea(shape: Shape): number {
  if (shape.type === "circle") {
    return Math.PI * shape.radius ** 2;
  } else {
    return shape.sideLength ** 2;
  }
}
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

6. Сборка Union типа

id: 40755_ts_discrim_union_06

Соберите из предложенных строк корректное определение discriminated union типа Shape, который представляет собой объединение типов Circle и Square. Каждый из этих типов должен иметь поле kind (строковый литерал) и своё уникальное поле (radius для Circle, sideLength для Square). Затем объявите тип Shape как объединение Circle и Square. Игнорируйте лишние строки, не относящиеся к определению этих типов.

Перетяните в правильном порядке строки из одного блока в другой
interface Circle {
  kind: 'circle';
  radius: number;
}
interface Square {
  kind: 'square';
  sideLength: number;
}
type Shape = Circle | Square;
interface Triangle {
color: string;
type Shape = Circle & Square;
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

7. Структура паттерна

id: 40755_ts_discrim_union_07

В этом коде TypeScript реализован паттерн Discriminated Union для обработки разных видов геометрических фигур. Разметьте выделенные фрагменты кода, указав для каждого, является ли он 'Общим интерфейсом', 'Дискриминантом' или 'Уникальным полем'. Общий интерфейс объединяет все типы объединения, дискриминант — это общее поле, определяющее конкретный тип, а уникальные поля — это свойства, специфичные для каждого типа.

Кликните по каждому выделенному фрагменту и выберите для него подходящий тип из списка под текстом.
interface {{Shape~|~t1}} {
{{kind~|~t2}}: 'circle' | 'rectangle' | 'triangle';
}

interface {{Circle~|~t3}} extends Shape {
kind: 'circle';
{{radius~|~t4}}: number;
}

interface {{Rectangle~|~t5}} extends Shape {
kind: 'rectangle';
{{width~|~t6}}: number;
{{height~|~t7}}: number;
}

interface {{Triangle~|~t8}} extends Shape {
kind: 'triangle';
{{base~|~t9}}: number;
{{height~|~t10}}: number;
}

type {{Geometry~|~t11}} = Circle | Rectangle | Triangle;
Уникальное поле
Дискриминант
Общий интерфейс
Сообщения
Проверить
Показать подсказку

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

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