Сужение типов: 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 — локальная установка не требуется.
Все уроки этого курса
- Обобщения: T extends и ограничения
- Вспомогательные типы: Partial, Required, Pick и Omit
- Отображаемые и условные типы
- Сужение типов: typeof, instanceof и дискриминируемые объединения