Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

30.11.2023

Типи та інтерфейси в TypeScript - в чому різниця?

Деякий час мене турбує питання — як це так, що в TypeScript можна створювати однакові типи як словом type, так і interface? Згадав про це з довідника по TS, в якому відповіді немає, зате багато чого цікавого є.

// виглядає ніби однаково
type T = { foo: string };
interface I {
  bar: number;
}
// і ніби використовується однаково:
interface E extends T, I {
  baz: boolean;
}

Так в чому різниця? В інтернеті можна знайти функціональне пояснення, тобто яка різниця у використанні, але мені більше цікавий сенс існування обох синтаксисів. Розібрався.

Типи в TypeScript, взагалі, не мають назв. Будь-яке значення має тип; він або задається явно, або виводиться з оточення. Якщо ми хочемо привʼязати до типу назву, то вживаємо ключове слово type, і оголошуємо псевдонім типу. Псевдонімом можна назвати будь-який тип, незалежно від складності.

Інтерфейс — це один з різновидів типів. А саме, це тип, який описує обʼєкт. Для перевірки типів що безіменний тип, що названий, що інтерфейс — абсолютно еквівалентні. Для успадкування теж практично байдуже, хіба що безіменний тип не можна успадкувати.

Є лише одна функція, доступна тільки через інтерфейс, оголошений словом interface. Це розширення інтерфейсу. Якщо оголосити інтерфейс з однаковим імʼям два рази, то типи будуть обʼєднані в один. Такий трюк особливо важливий для бібліотек, бо традиційно в JavaScript заведено підсипати функціонал до обʼєктів, які вже існують — на кшталт window.jQuery. Про це я вже писав. Причому, типи так само можна розширювати, але не під тою самою назвою. Але в межах одного проєкту це не тільки прийнятно, а навпаки — бажано.

Виходить, що оголошення interface утворює точку розширення, в цьому його сенс. Оскільки іншої різниці реально немає, то я б використовував interface тільки саме з цим наголосом.