Discriminated Unions

Discriminated Union

Якщо у вас є клас ізliteral member, ви можете використовувати цю властивість для розрізнення членів об’єднання.

Як приклад розглянемо об’єднання Square і Rectangle, тут ми маємо член kind який існує в обох членах об’єднання та має певний literal type:

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

interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}
type Shape = Square | Rectangle;

Якщо ви використовуєте перевірку стилю захисту типу (==, ===, !=, !==) або switch на discriminant property (тут kind) TypeScript зрозуміє що об’єкт має бути типу, який має цей конкретний літерал, і додасть тип за вас :)

function area(s: Shape) {
    if (s.kind === "square") {
        // Зараз TypeScript *знає* що `s` має бути square ;)
        // Тож ви можете безпечно використовувати його учасників :)
        return s.size * s.size;
    }
    else {
        // Це не square? TypeScript зрозуміє, що це має бути Rectangle ;)
        // Тож ви можете безпечно використовувати його учасників :)
        return s.width * s.height;
    }
}

Exhaustive Checks

Вичерпні перевірки.

Досить часто ви хочете переконатися, що всі члени мають певний код

Як приклад того, де все йде погано:

Ви можете зробити це, просто додавши пропуск і переконавшись, що виведений тип у цьому блоці сумісний із типом never. Наприклад, якщо ви додасте вичерпну перевірку, ви отримаєте гарну помилку:

Це змушує вас розглядати цю нову справу:

Switch

ПОРАДА: звичайно, ви також можете зробити це в операторі switch:

strictNullChecks

Якщо використовується strictNullChecks і виконуються вичерпні перевірки, TypeScript може скаржитися, що «не всі шляхи коду повертають значення». Ви можете заглушити це, просто повернувши змінну _exhaustiveCheck (типу never). Так:

Throw in exhaustive checks

Ви можете написати функцію, яка приймає never (і тому може бути викликана лише зі змінною, яка виводиться як never), а потім видає помилку, якщо її тіло коли-небудь виконується:

Приклад використання функції площі:

Retrospective Versioning

Скажімо, у вас є структура даних у формі:

І після того, як у вас є купа DTO, ви розумієте, що name було поганим вибором. Ви можете додати керування версіями ретроспективно, створивши новий union з literal number (або рядком, якщо хочете) DTO. Позначте версію 0 як undefined якщо у вас увімкнено strictNullChecks, це просто спрацює:

Приклад використання такого DTO:

Redux

Популярною бібліотекою, яка використовує це, є redux.

Ось gist of reduxіз доданими анотаціями типу TypeScript:

Використання його з TypeScript забезпечує захист від друкарських помилок, покращує здатність до рефакторингу та самодокументування коду.

Last updated