К списку постов

Тип never в Typescript

Типизация - это то, почему многие выбирают писать на TypeScript, а не на чистом JavaScript. Хотя на конференциях можно услышать доклады "Почему вам не нужен TS", в больших проектах без него просто не обойтись. А если писать на нём регулярно, то уже даже в небольших проектах обычный JS будет приносить только боль. Я это ощутил, при подготовке уроков по NodeJS для следующего курса, где не используется TypeScript.

Потому важно понимать все особенности типизации. Разберём тип never, который многим, кто знакомится с TypeScript непонятен.

Не путать с void!

Тип void в возвращаемом типе функции, обозначает что функция ничего не возвращает (или по иному говоря возвращает undefined).

const a = (): void => {
    return undefined;
}

В свою очередь переменной типа never можно присвоить только тип never и никакой другой. Кажется бесполезным? Рассмотрим 3 примера использования:

Исчерпывающие проверки типов

Вот пример функции, которая возвращает тип never:

export const error = (message: string): never => {
    throw new Error(message);
}

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

export const typeRun = (x: string | number): boolean => {
    if (typeof x === 'string') {
        return true;
    } else if (typeof x === 'number') {
        return false;
    }
    return error("!");
}

Если бы не использовали never, TS бы выдавал ошибку, так как мы в теории могли бы попасть дальше проверки и вернуть undefined вместо boolean.

Switch / case

Рассмотрим следующий пример:

export type Direction = 'up' | 'down';
export const run = (direction: Direction) => {
    switch (direction) {
        case 'up':
            return 1;
        case 'down':
            return -1;
        default:
            const a: never = direction;
        }
}

Если у нас в Direction добавится новое направление, скажем right, то TypeScript за счёт типа подскажет, что у нас switch больше не валиден, так как при новом значении Direction мы уже можем попасть в default и у нас типу never будет присвоено значение другого типа, что недопустимо.

Conditional types

Благодаря never мы можем исключить не нужные типы. Например, сделаем тип, который если у нас передано значение с number мы присваиваем never. Тем самым мы оставляем только нужный тип в типе А:

type NonNumber<T> = T extends number ? never : T;

type A = NonNumber<string | number>; // A - всегда string

Подпишись на статьи

Всего 1 раз в месяц я буду высылать вам подборки свежих статей с сайта.

Если хотите получать материалы и статьи каждую неделю подпишитесь на канал в Telegram PurpleCode.