Загрузка…
Загрузка…
TypeScript · middle · сложность 5
interface и type для object shapes взаимозаменяемы на ~90%. Реальные отличия: interfaces merge и extend (открыты, удобны для публичных API и augmentation), а type aliases именуют что угодно — unions, tuples, primitives, mapped/conditional — и закрыты.
interface описывает форму объекта/класса, поддерживает extends и declaration merging. type — алиас любого типа; повторное объявление с тем же именем — ошибка.
Для библиотечных extension points почти всегда interface (merging). Для Status = 'a' | 'b' — только type. В прикладном коде важнее конвенция команды, чем микроразличия.
// Only interfaces merge — this is how you augment third-party/global types
interface Window { myAnalytics: (e: string) => void; }
interface Window { featureFlags: Record<string, boolean>; } // merges, both exist
window.myAnalytics('signup'); // ✅ typed
// Only type aliases can name non-object types
type ID = string | number; // union — impossible as an interface
type Point = [number, number]; // tuple
type Handler = (e: Event) => void; // function type (reads cleanly)
type Nullable<T> = T | null; // generic alias over anything
// Extension: both work for objects, different machinery
interface Animal { name: string; }
interface Dog extends Animal { bark(): void; } // named inheritance
type Cat = Animal & { meow(): void; }; // intersection
// ❌ can't do this — alias for a shape can't be reopened
type Cfg = { a: number };
type Cfg = { b: number }; // Error: Duplicate identifier 'Cfg'// Subtle: interface extends enforces compatibility; intersection silently narrows to never
interface A { x: number }
// interface B extends A { x: string } // ❌ Error: incompatible — caught early
type C = A & { x: string }; // no error; C['x'] is `never` — a silent trapObject shapes — почти всё равно; merging/augmentation → interface; unions и вычисляемые типы → type. Consistency важнее споров.