Чем interface отличается от type в TypeScript и когда что использовать?
Короткий ответ
- Оба описывают форму объекта, во многом взаимозаменяемы
- type умеет объединения, пересечения, кортежи, mapped types
- interface поддерживает слияние деклараций (declaration merging)
- interface расширяется через extends, type — через пересечение &
- Слияние нужно для дополнения внешних типов библиотек
- Типы стираются при компиляции, в рантайме их нет
- Главное — единый стиль в команде
interface — про расширяемые контракты объектов и слияние деклараций, type — универсальный псевдоним, умеющий объединения и вычисляемые типы; в остальном выбор — вопрос конвенции.
Как сказать вслух
пример ответаДля описания формы объекта они почти эквивалентны, разница в возможностях по краям. type — это псевдоним любого типа: им можно описать объединение, кортеж, примитив, вычисляемый тип. interface работает только с объектными формами, зато поддерживает слияние: два объявления с одним именем объединяются, так дополняют типы сторонних библиотек. Я обычно беру interface для публичных контрактов и type для объединений и утилитарных типов, но главное — договорённость в команде.
Подробный ответ
Основной ответ
interface описывает объектную форму и может расширяться через extends; одноимённые интерфейсы в одной области видимости сливаются в один — это основа механизма дополнения типов чужих модулей (declaration merging, module augmentation). type создаёт псевдоним для любого типа: объединения (A | B), пересечения (A & B), кортежи, литеральные, условные и mapped types — всё это выражается только через type. Пересечение с конфликтующими полями молча даёт never, тогда как extends с несовместимым полем сразу подсветит ошибку, поэтому для иерархий контрактов интерфейсы читаются надёжнее. В рантайме ни того ни другого нет — типы полностью стираются при компиляции, проверить их во время выполнения нельзя, для этого пишут type guards или используют схемы валидации вроде zod.
Ключевые моменты
- Возможности type. Объединения, кортежи, условные и mapped types доступны только через type.
- Слияние interface. Повторное объявление интерфейса дополняет его — так расширяют типы библиотек и глобальные объекты.
- extends против &. extends проверяет совместимость при объявлении, пересечение может тихо схлопнуться в never.
- Стирание типов. В собранном JS типов нет; для проверки данных в рантайме нужны guards или схемы валидации.
Практический контекст
В работе это проявляется при описании пропсов компонентов, API-ответов и общих моделей. Интервьюер смотрит, понимает ли кандидат структурную типизацию и стирание типов, а не только синтаксис. Частое продолжение — попросить описать тип пропсов с объединением вариантов (discriminated union) или объяснить, как типизировать ответ сервера, которому нельзя доверять.
Частые ошибки
- Утверждают, что interface «быстрее» или «правильнее» без аргументов
- Не знают про declaration merging и зачем он нужен
- Пытаются проверять типы в рантайме через instanceof для интерфейсов