Название фичи: Union

Описание:

Описывает значение, которое может быть одним из нескольких типов. Используется вертикальная черта (|), чтобы отделить каждый тип.
Аналог в c# / js: StructLayoutAttribute

Решаемая проблема:

Разработчик с одной стороны не может точно определить единственный тип входящего параметра функции (например, в один момент времени в него могут передать число, в другой момент - строку), а с другой стороны ему хочется иметь проверку типов на момент компиляции при вызове функции, чтобы её нельзя было вызвать с некорректным типом параметра.

Пример возникновения:

Разработчик получает значения переменной из динамического контента, например от пользователя или от сторонней JS библиотеки и для нее есть набор подходящих типов. Функция может работать для нескольких типов входного аргумента, но не для всех возможных JavaScript типов.

Пример проблемы на JavaScript:

function padLeft(value, padding) {
    if(typeof padding !== "number") {
        padding = Number(padding.trim());
    }
    ...
}

let indentedString1 = padLeft("Hello world", 10);     // работает
let indentedString2 = padLeft("Hello world", " 10 "); // работает
let indentedString3 = padLeft("Hello world", true);   // падает: padding.trim is not a function

Пример решения на TypeScript:

function padLeft(value: string, padding: string | number) {
    // ...
}

let indentedString1 = padLeft("Hello world", 10);
let indentedString2 = padLeft("Hello world", " 10 ");
let indentedString3 = padLeft("Hello world", true);   // выведет ошибку во время компиляции

Как решить проблему:

Разработчик ограничивает набор типов и позволяет значениям пройти проверку на этапе компиляции.

Синтаксис:

function padLeft(value: string, padding: string | number) {
    // ...
}

Перекомпилированный в JSкод:

function padLeft(value, padding) {
    // ...
}

Важно учесть:

Если у нас есть значение типа объединения, вы можете получить доступ только к тем его элементам, которые являются общими для всех типов в объединении.

Иначе говоря, если значение имеет тип A | B, мы знаем, что оно имеет только те элементы, которые имеют оба A и B.

Например:

interface Bird {
    fly();
    layEggs();
}

interface Fish {
    swim();
    layEggs();
}

function getSmallPet(): Fish | Bird {
    // ...
}

let pet = getSmallPet();
pet.layEggs(); // ок
pet.swim();    // ошибка

В этом примере Bird имеет элемент именованный fly. Мы не можем быть уверены в том, есть ли у переменной, имеющей тип Bird | Fish, метод fly. Если переменная во время выполнения на самом деле является Fish, тогда вызов pet.fly() не выполнится.

results matching ""

    No results matching ""