0Pricing
Frontend Academy · Урок

Сужение типов: typeof, instanceof и дискриминируемые объединения

Используйте защитники типов, чтобы сужать типы-объединения во время выполнения с помощью typeof, instanceof и шаблонов дискриминируемых объединений.

«Сужение типов: typeof, instanceof и дискриминируемые объединения» — бесплатный урок Frontend Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Frontend Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Frontend Academy содержит 4 уроков всего.

Что такое сужение типа?

TypeScript начинает с широкого типа, например string | number. Сужение — это процесс уточнения типа до более конкретного внутри условного блока. TypeScript отслеживает сужение автоматически.

Сужение с помощью typeof

Оператор typeof сужает примитивные типы. Внутри блока if TypeScript знает точный тип.

function format(value: string | number | boolean): string {
  if (typeof value === 'string') {
    return value.toUpperCase(); // string here
  }
  if (typeof value === 'number') {
    return value.toFixed(2);   // number here
  }
  return String(value);        // boolean here
}

Сужение с помощью instanceof

instanceof сужает типы экземпляров классов. Внутри блока TypeScript знает конкретный класс.

function processError(err: unknown) {
  if (err instanceof Error) {
    console.error(err.message); // Error methods available
  } else if (err instanceof Response) {
    console.error('HTTP error:', err.status);
  } else {
    console.error('Unknown:', err);
  }
}

Сужение по истинности

TypeScript исключает null и undefined при проверках на истинность.

function printLength(value: string | null | undefined) {
  if (value) {
    console.log(value.length); // string here (null/undefined filtered)
  }
}

Сужение по равенству

Строгое равенство сужает тип до литерального типа. Это полезно для дискриминируемых объединений и строковых перечислений.

function handle(action: 'submit' | 'cancel' | 'reset') {
  if (action === 'submit') {
    // action is exactly 'submit'
    doSubmit();
  }
}

Сужение с помощью оператора in

Оператор in сужает объединения типов объектов, проверяя наличие свойств.

interface Cat { meow(): void; }
interface Dog { bark(): void; }

function speak(animal: Cat | Dog) {
  if ('meow' in animal) {
    animal.meow(); // Cat
  } else {
    animal.bark(); // Dog
  }
}

Дискриминируемые объединения — сужение по метке

Дискриминируемое объединение содержит общее свойство с литеральным типом — дискриминатор. TypeScript сужает объединение в конструкции switch или if на основе этого свойства.

type LoadingState = { status: 'loading' };
type SuccessState = { status: 'success'; data: User[] };
type ErrorState   = { status: 'error'; message: string };
type State = LoadingState | SuccessState | ErrorState;

function render(state: State) {
  switch (state.status) {
    case 'loading': return '<Spinner />';
    case 'success': return renderUsers(state.data);  // state.data available
    case 'error':   return renderError(state.message);
  }
}

Предикаты типов — пользовательские защитные функции типов

Функция-предикат типа сужает тип для вызывающего кода. Используйте param is Type как возвращаемый тип.

function isUser(value: unknown): value is User {
  return (
    typeof value === 'object' &&
    value !== null &&
    'name' in value &&
    typeof (value as User).name === 'string'
  );
}

const data: unknown = await fetchJson('/api/me');
if (isUser(data)) {
  console.log(data.name); // typed as User
}

Функции утверждений

Функция утверждения выбрасывает исключение, если условие не выполнено, и сужает тип после вызова.

function assertIsString(val: unknown): asserts val is string {
  if (typeof val !== 'string') throw new Error('Expected string');
}

const val: unknown = getInput();
assertIsString(val);
console.log(val.toUpperCase()); // val is string here

Проверка полноты вариантов

Если при обработке дискриминируемого объединения в конструкции switch в ветви default остаётся тип never, TypeScript проверяет, что обработаны все варианты. Добавьте default, присваивающий значение never, чтобы при добавлении нового варианта получить ошибку компиляции.

function render(state: State): string {
  switch (state.status) {
    case 'loading': return '...';
    case 'success': return state.data.length.toString();
    case 'error':   return state.message;
    default:
      const _exhaustive: never = state;
      throw new Error('Unhandled state: ' + _exhaustive);
  }
}

Сужение с помощью Array.isArray

Array.isArray() сужает значение до типа массива.

function processInput(input: string | string[]) {
  if (Array.isArray(input)) {
    return input.join(', '); // string[]
  }
  return input.toUpperCase(); // string
}

Быстрая проверка

Какая техника сужения использует общее свойство с литеральным типом, чтобы различать варианты объединения типов?

Итоги: сужение типов в TypeScript

typeof — для примитивных типов. instanceof — для классов. Оператор in — для структуры объектов. Проверка на истинность отфильтровывает null и undefined. Дискриминируемые объединения с общим свойством литерального типа позволяют создавать исчерпывающие конструкции switch. Пользовательские предикаты типов (is) — для сложных проверок во время выполнения. Проверка полноты вариантов с помощью never в ветвях default.

Часто задаваемые вопросы

Урок «Сужение типов: typeof, instanceof и дискриминируемые объединения» бесплатный?

Да — полный текст урока «Сужение типов: typeof, instanceof и дискриминируемые объединения» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Frontend Academy, подпишись на CoddyKit PRO. Курс Frontend Academy содержит 4 уроков всего.

Чему я научусь в уроке «Сужение типов: typeof, instanceof и дискриминируемые объединения»?

Используйте защитники типов, чтобы сужать типы-объединения во время выполнения с помощью typeof, instanceof и шаблонов дискриминируемых объединений. Ты практикуешь Frontend Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Frontend Academy?

Предыдущий опыт не требуется. Frontend Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Сужение типов: typeof, instanceof и дискриминируемые объединения»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Frontend Academy?

Да. Каждый урок Frontend Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Обобщения: T extends и ограничения
  2. Вспомогательные типы: Partial, Required, Pick и Omit
  3. Отображаемые и условные типы
  4. Сужение типов: typeof, instanceof и дискриминируемые объединения
← Назад к Frontend Academy