TypeScript: type vs interface

В чём разница между type и interface?

type и interface во многом взаимозаменяемы, но имеют ключевые отличия.

// interface — описывает форму объекта или класса
interface User {
  name: string;
  age: number;
}
 
// type — описывает любой тип, не только объект
type ID = string | number;
type Callback = (value: string) => void;
type Point = { x: number; y: number };

Расширение

// interface — через extends
interface Animal { name: string; }
interface Dog extends Animal { breed: string; }
 
// type — через пересечение (&)
type Animal = { name: string };
type Dog = Animal & { breed: string };

Declaration Merging — только у interface

// interface можно дополнять в разных местах кода
interface Window { myProp: string; }
interface Window { anotherProp: number; }
// Итог: Window имеет оба свойства ✅
 
// type — нельзя объявить дважды с одним именем
type Window = { myProp: string; };
type Window = { anotherProp: number; }; // ❌ Error: Duplicate identifier

Declaration merging используется для расширения глобальных типов (например, Window, ProcessEnv).


Уникальные возможности type

// Union — объединение типов
type Status = 'active' | 'inactive' | 'banned';
type ID = string | number;
 
// Tuple — массив с фиксированными типами позиций
type Pair = [string, number];
const p: Pair = ['hello', 42];
 
// Mapped types
type Readonly<T> = { readonly [K in keyof T]: T[K] };
type Optional<T> = { [K in keyof T]?: T[K] };
 
// Conditional types
type IsString<T> = T extends string ? true : false;

Когда что использовать?

СитуацияВыбор
Форма объекта / API-контрактinterface
Публичные библиотеки (для merging)interface
Классы и их контрактыinterface
Union / Intersection типыtype
Примитивные псевдонимы (type ID)type
Tuple, Mapped types, Conditional typestype

Практическое правило: используй interface для объектов и классов, type — для всего остального.