Перейти к содержанию
Innovialabs

type или interface в TypeScript: что и когда использовать

Практика3 мин

Коротко

Для описания формы объекта type и interface почти взаимозаменяемы. interface нужен, когда важны extends и слияние объявлений, type — для union, кортежей и вычисляемых типов. Главное — договориться о правиле в команде.

Короткий ответ

Для обычного объекта разницы почти нет:

type UserT = { id: number; name: string };
interface UserI { id: number; name: string }

Оба варианта работают одинаково в функциях, классах и пропсах компонентов. Различия проявляются в четырёх местах: слияние объявлений, union и другие не-объектные типы, extends против пересечений и сообщения об ошибках.

Различие 1: слияние объявлений

Два interface с одним именем автоматически объединяются:

interface Config { apiUrl: string }
interface Config { timeout: number }

const c: Config = { apiUrl: "/api", timeout: 5000 }; // оба поля обязательны

С type так нельзя — повторное объявление даст ошибку Duplicate identifier.

Когда это полезно: расширение чужих типов — например, добавить поле в глобальный Window или в типы библиотеки. Когда вредно: случайное совпадение имён в разных файлах молча меняет тип.

Различие 2: union и не-объектные типы

interface описывает только форму объекта. type умеет всё остальное:

type Status = "idle" | "loading" | "error";
type Id = string | number;
type Point = [number, number];
type Handler = (event: MouseEvent) => void;
type ReadonlyUser = Readonly<UserT>;
type Result =
  | { ok: true; data: string }
  | { ok: false; error: string };

Union-типы, кортежи, mapped и conditional types — территория type.

Различие 3: extends против пересечений

Наследование можно записать двумя способами:

interface Base { id: number }
interface Admin extends Base { role: "admin" }

type BaseT = { id: number };
type AdminT = BaseT & { role: "admin" };

Разница видна при конфликте свойств:

interface A { value: string }
interface B extends A { value: number }
// Ошибка сразу: Interface 'B' incorrectly extends interface 'A'

type C = { value: string } & { value: number };
// Ошибки нет, но value имеет тип never — проблема всплывёт позже

extends проверяет совместимость в момент объявления, пересечение & молча создаёт невозможный тип. Кроме того, документация TypeScript отмечает, что иерархии через interface extends компилятор обрабатывает эффективнее, чем большие пересечения.

Различие 4: сообщения об ошибках

В подсказках и ошибках interface обычно показывается по имени, а сложный type из пересечений и утилит может раскрываться в длинную структуру. В большом проекте это заметно влияет на читаемость ошибок. Разница не принципиальная, но приятная в пользу interface для объектов.

Что умеют оба

  • Описывать объекты, методы, необязательные и readonly поля.
  • Использоваться в implements у классов (если type описывает объект, а не union).
  • interface может расширять type, а type — пересекаться с interface.
  • Поддерживать дженерики: interface Box<T> { value: T } и type Box<T> = { value: T }.

Сравнительная таблица

Возможностьtypeinterface
Форма объектаДаДа
Union, кортежи, примитивыДаНет
Mapped / conditional typesДаНет
Слияние объявленийНетДа
Проверка конфликтов при наследованииНет (& даёт never)Да (extends)
Имя в сообщениях об ошибкахНе всегдаОбычно да

Простое правило для команды

Рабочий вариант, который легко соблюдать:

  1. interface — для форм объектов: модели данных, пропсы компонентов, контракты API, публичные типы библиотеки.
  2. type — для union, кортежей, функций и всего, что собрано из утилит (Pick, Omit, Partial).
  3. Наследование — через extends, а не через &, если это возможно.
  4. Слияние объявлений — только осознанно, для расширения внешних типов.

Альтернатива «везде type, interface только для расширения внешних типов» тоже нормальна. Важнее выбрать одно и закрепить его линтером: в typescript-eslint есть правило consistent-type-definitions.

Частые вопросы

Нет. Типы удаляются при компиляции и не влияют на работу кода. Разница возможна только в скорости проверки типов в очень больших проектах.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.