Интервью-вопрос
Что такое instanceof в TypeScript
instanceof проверяет принадлежность объекта к классу во время выполнения по цепочке прототипов. В TypeScript он полезен как type guard для классов, но не заменяет проверку интерфейсов, примитивов и plain objects из API.
- Добавлен
- Редакция
Подготовьте короткий ответ и пару деталей на случай уточняющих вопросов.
Мини-квиз
Проверка перед разбором
Несколько быстрых вопросов перед разбором. Так проще поймать места, которые только кажутся понятными.
Вопрос 1 из 50 правильно
Разбор
Разобраться, а не зазубрить
Дальше разбираем суть, типичные уточнения и места, где легко сказать лишнее или перепутать термины.
Базовая идея
Короткий ответ можно начать с главного: instanceof проверяет не название типа и не набор полей. Он проверяет прототипную цепочку объекта. Справа стоит класс или функция-конструктор, слева значение. Если Constructor.prototype найден в цепочке прототипов значения, результат будет true.
Для TypeScript здесь есть два важных вывода. Оператор реально выполняется в браузере или Node.js. А еще TypeScript умеет использовать результат проверки как type guard и сужает тип внутри ветки.
class NetworkError extends Error {
status = 500;
}
function showError(error: unknown) {
if (error instanceof NetworkError) {
// error сужен до NetworkError
return `Request failed with status ${error.status}`;
}
if (error instanceof Error) {
return error.message;
}
return "Unknown error";
}На практике используйте instanceof, когда у вас есть реальные классы и экземпляры. Не подменяйте им проверку любых TypeScript-типов.
Что именно проверяется
В JavaScript объекты связаны с прототипами. Когда вы пишете value instanceof User, движок не сравнивает поля value с полями класса User. Он ищет User.prototype в цепочке прототипов value.
class User {
constructor(public name: string) {}
}
const realUser = new User("Ann");
const plainUser = { name: "Ann" };
console.log(realUser instanceof User); // true
console.log(plainUser instanceof User); // falseЭтот пример удобно привести на интервью. Объекты выглядят похоже по полям, но результат разный. Один создан через new User, а второй является обычным объектом.
Как выбрать проверку
Сильный ответ не заканчивается определением. Покажите, что выбираете проверку по источнику значения. Во frontend значения часто приходят из форм, API, localStorage, iframe и сторонних виджетов. Для них один и тот же инструмент не всегда подходит.
Как выбрать проверку типа
Используйте typeof. instanceof здесь даст неверную интуицию и не проверит обычные примитивы.instanceof уместен. TypeScript сузит тип внутри ветки, а runtime проверит прототипы.Не полагайтесь на instanceof. Проверьте форму объекта или валидируйте данные явно, иначе UI может показать fallback или ошибку для корректных данных.Лучше discriminated union. Это проще читать и безопаснее для состояния UI.Используйте Array.isArray, а не value instanceof Array.Ограничение TypeScript: интерфейсы исчезают
TypeScript проверяет форму значения на этапе компиляции. Интерфейс нужен компилятору, но после сборки в JavaScript его нет. Поэтому такой код писать нельзя:
interface User {
id: string;
name: string;
}
function handle(value: unknown) {
// Плохой пример: User это не runtime-значение
if (value instanceof User) {
console.log(value.name);
}
}Такой код не скомпилируется, потому что User существует только как тип. Дальше выбор зависит от модели. Для union-состояния удобно добавить поле-дискриминатор. Для данных с сервера лучше написать проверку формы или использовать валидатор.
type LoadState =
| { kind: "idle" }
| { kind: "success"; user: { id: string; name: string } }
| { kind: "error"; message: string };
function render(state: LoadState) {
if (state.kind === "success") {
return state.user.name;
}
if (state.kind === "error") {
return state.message;
}
return "Loading";
}Такой вариант проще поддерживать в UI. Состояние явно описано, TypeScript хорошо сужает тип, а проверка не зависит от прототипов.
Примитивы, массивы и данные из API
Для строк, чисел и boolean обычно нужен typeof. Проверка через instanceof String или instanceof Number ищет объект-обертку, а не обычный примитив. В интерфейсе это может привести к плохому UX. Пользователь ввел нормальную строку, но код решил, что тип неверный.
const name = "Ann";
console.log(name instanceof String); // false
console.log(typeof name === "string"); // trueДля массивов часто лучше использовать Array.isArray. Это особенно полезно в браузере, где значение может прийти из другого окна или iframe. value instanceof Array привязан к конкретному конструктору Array, а Array.isArray проверяет массив надежнее.
С данными из API есть отдельная ловушка. После JSON.parse вы получаете plain object, а не экземпляр вашего класса. Даже если у объекта есть все нужные поля, payload instanceof User вернет false, пока вы явно не создадите new User(...).
class User {
constructor(public id: string, public name: string) {}
}
const payload: unknown = JSON.parse(responseText);
// Плохой вариант: валидный ответ API уйдет в состояние ошибки,
// потому что payload не является экземпляром класса User.
if (payload instanceof User) {
setUser(payload);
} else {
setError("Bad response");
}Безопаснее проверить форму ответа и отдельно решить, нужен ли вам экземпляр класса. Так UI не покажет ошибку только из-за того, что у объекта нет нужного прототипа.
function isUserPayload(value: unknown): value is { id: string; name: string } {
return (
typeof value === "object" &&
value !== null &&
"id" in value &&
typeof value.id === "string" &&
"name" in value &&
typeof value.name === "string"
);
}
if (isUserPayload(payload)) {
setUser(new User(payload.id, payload.name));
} else {
setError("Bad response");
}Как звучит сильный ответ
На интервью можно сказать так:
instanceofв TypeScript это тот же оператор JavaScript. Он проверяет, есть ли prototype конструктора в цепочке прототипов объекта. TypeScript использует такую проверку как type guard и сужает тип внутри if. Я бы применял его для реальных классов, например Error или собственных классов доменной модели. Для interface, type alias, объектов из JSON и примитивов нужны другие проверки: typeof, in, discriminated union или пользовательский type guard.
Такой ответ звучит уверенно. Вы показываете границу между compile time и runtime. Еще вы не обещаете, что TypeScript проверит то, чего нет в JavaScript, и сразу называете практические альтернативы.
Практический вывод для frontend
Во frontend-коде instanceof чаще всего уместен для ошибок, классовых моделей и объектов, которые вы точно создали через new. Например, проверка error instanceof Error помогает безопасно достать message из unknown в обработчике запроса.
Но для ответов API, данных из форм и состояния React чаще лучше проверять форму данных. Иначе можно получить ветку, которая никогда не выполнится, лишний fallback, неверный текст ошибки или состояние UI, которое не соответствует реальным данным.
Частые ошибки
Где обычно ошибаются
Проверьте формулировки, которые звучат уверенно, но на интервью быстро выдают пробелы.
- 1
Называть instanceof проверкой типов TypeScript
instanceofработает в runtime и остается в JavaScript после компиляции. TypeScript только использует результат условия для сужения типа. Если сказать, что оператор проверяет интерфейсы TypeScript, вас легко поймают вопросом про исчезновение типов после сборки. - 2
Проверять интерфейс или type alias
Интерфейс нельзя поставить справа отinstanceof, потому что его нет в JavaScript. Для plain object лучше добавить поле-дискриминатор, напримерkind, или написать функциюisUser(value). Иначе код либо не скомпилируется, либо создаст ложное чувство безопасности. - 3
Использовать instanceof для обычных строк и чисел
'42' instanceof Stringвернетfalse, потому что это примитив, а не объект-обертка. Для таких значений используйтеtypeof value === 'string'. Ошибка часто приводит к тому, что валидные значения из формы попадают в ветку ошибки. - 4
Доверять instanceof для данных из JSON
Объект послеJSON.parseимеет обычный прототип и не становится экземпляром вашего класса. Проверкаpayload instanceof Userвернетfalse, даже если поля похожи. Нужно либо создать экземпляр явно, либо валидировать форму данных. - 5
Забывать про разные глобальные контексты
В браузере iframe и основная страница могут иметь разные конструкторы. Из-за этогоvalue instanceof Arrayможет дать неожиданный результат для массива из другого окна. Для массивов лучше сказать проArray.isArray.
Follow-up
Что могут спросить дальше
Короткие ответы на вопросы, которыми проверяют понимание runtime-проверок, прототипов и границ TypeScript.
Живые ответы
Видео с похожим вопросом
Если найдем публичные интервью с таким вопросом, добавим их сюда. Их удобно смотреть после теории, чтобы свериться с живыми ответами.
Пока видео нет. Когда появятся подходящие публичные интервью, добавим их в этот блок, чтобы можно было сравнить разбор с тем, как отвечают реальные кандидаты.
Что такое Function Overload в TypeScript 😎
Function Overload позволяет описать несколько публичных сигнатур одной функции и связать тип результата с типами аргументов. На странице разбираем синтаксис, порядок перегрузок, отличие от union types и частые ловушки в frontend-коде.
Что такое keyof 😎
keyof в TypeScript получает union ключей типа и помогает безопасно работать со свойствами объектов. Разбираем, чем он отличается от Object.keys, как сочетается с generics и где легко ошибиться.