ПрограммированиеFrontend разработчик

Объясните, как работает тип guard-оператор typeof в TypeScript, как и для чего его используют, и какие у него ограничения?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

История вопроса

В JavaScript оператор typeof используется для проверки типа примитивных значений во время выполнения. TypeScript расширяет этот механизм и делает его частью системы сужения типов (type narrowing) через типовые защиты (type guards). TypeScript использует результат оператора typeof для уточнения типа переменной внутри блока кода, что позволяет более точно описывать логику работы функции, особенно при работе с union-типами.

Проблема

В обычном JavaScript после проверки типа значения с помощью typeof никакой типовой гарантии быть не может — программист должен помнить, что происходит на каком участке кода. Однако, в TypeScript задача усложняется присутствием разных типов и union-типов, и без корректного сужения типов легко сделать ошибку, например, обратиться к несуществующему методу. Также у оператора есть конкретные ограничения: он "видит" только базовые примитивные типы, например, для массивов и объектов вернёт 'object'.

Решение

TypeScript позволяет комбинировать оператор typeof с собственным анализом типов для сужения типа переменной внутри блока кода. Это автоматически повышает безопасность — компилятор знает, с каким типом работает код, и подсказывает возможные свойства и методы.

Пример кода:

function printId(id: number | string) { if (typeof id === 'string') { // В этой ветке id: string console.log(id.toUpperCase()); } else { // В этой ветке id: number console.log(id.toFixed(2)); } }

Ключевые особенности:

  • Работает только с примитивами: 'string', 'number', 'boolean', 'symbol', 'undefined', 'object', 'function', 'bigint'.
  • Помогает TypeScript сузить union-тип до конкретного примитива внутри блока кода.
  • Не различает массивы и объекты, всегда возвращает 'object' для них.

Вопросы с подвохом.

Может ли оператор typeof определить массив?

Нет, typeof для массива и объекта вернёт одно и то же значение — 'object'. Для выделения массивов лучше использовать метод Array.isArray().

Пример кода:

const arr = [1, 2, 3]; console.log(typeof arr); // 'object' console.log(Array.isArray(arr)); // true

Можно ли с помощью typeof различить null и объект?

Нет, typeof null возвращает 'object', это историческая особенность JavaScript.

Пример кода:

console.log(typeof null); // 'object'

Можно ли с помощью typeof проверить пользовательский класс?

Нет, для экземпляров классов typeof также вернёт 'object'. Для этого используют оператор instaceof или пользовательские type guard-функции.

Пример кода:

class User {} const u = new User(); console.log(typeof u); // 'object' console.log(u instanceof User); // true

Типовые ошибки и анти-паттерны

  • Использование typeof для проверки сложных структур данных (например, массивов, null, объектов).
  • Пренебрежение использованием операторов instanceof и Array.isArray() для более точного сужения типа.
  • Проверка типов только на уровне рантайма, игнорируя статическую проверку.

Пример из жизни

Негативный кейс

Программист написал функцию, где хотел проверить, является ли value массивом через typeof, и на основании результата вызывать разные методы.

Плюсы:

  • Просто написан код.
  • Не требует доп. функций.

Минусы:

  • Функция ломается при передаче массива: массив воспринимается как объект, ошибки в рантайме.

Позитивный кейс

Использование Array.isArray и комбинирование с type guard.

Плюсы:

  • Безопасная статическая типизация.
  • Отсутствие ошибок с типами объектов versus массивов.

Минусы:

  • Нужно помнить про разные type guard-инструменты.