Skip to main content

Що означає "структурна типізація"?

1. Суть структурної типізації

Структурна типізація означає, що два типи вважаються сумісними, якщо у них однакова структура (тобто однаковий набір властивостей та їх типів), навіть якщо вони були оголошені по-різному.

Іншими словами: TypeScript дивиться не на ім'я типу, а на його форму (shape).


Приклад

javascript
interface User { id: number; name: string; } const person = { id: 1, name: "Tim", age: 25 }; function printUser(user: User) { console.log(user.name); } printUser(person); // коректно!

Хоча person не оголошений як тип User, TypeScript приймає його, тому що він сумісний за структурою (у нього є всі потрібні поля: id та name).

TypeScript не перевіряє, як об'єкт створений, він перевіряє, чи є у нього потрібні властивості потрібних типів.


2. Протилежність - "номінальна типізація"

У мовах з номінальною типізацією (наприклад, Java, C#, Swift) два типи вважаються сумісними тільки якщо вони оголошені як пов'язані (наприклад, через успадкування або спільне ім'я).

Приклад (у стилі Java):

javascript
class User { int id; String name; } class Person { int id; String name; } // User та Person несумісні, навіть якщо поля однакові

А у TypeScript:

javascript
interface User { id: number; name: string } interface Person { id: number; name: string } let user: User = { id: 1, name: "Tim" }; let person: Person = user; // OK - однакова структура

TypeScript не хвилює, що це "різні інтерфейси", важлива лише форма об'єкта.


3. Приклад несумісності

Якщо бракує хоча б однієї властивості або тип відрізняється - несумісно:

javascript
interface User { id: number; name: string; } const invalid = { id: "1", name: "Tim" }; // id не число let u: User = invalid; // Помилка: id має бути number

4. Як TypeScript перевіряє сумісність

TypeScript йде "за структурою" об'єкта:

  1. Дивиться на всі обов'язкові поля цільового типу.
  2. Перевіряє, що у переданого значення є ті самі поля з сумісними типами.
  3. Ігнорує зайві властивості (якщо вони не заважають контексту).

5. Приклад зі складними структурами

javascript
interface Point { x: number; y: number; } interface Coordinates { x: number; y: number; } const draw = (p: Point) => console.log(p.x, p.y); const c: Coordinates = { x: 10, y: 20 }; draw(c); // Сумісно - однакова структура

6. Чому це корисно

Структурна типізація робить код:

  • гнучкішим - не потрібно явно успадковувати типи;
  • простішим для тестування і підміни об'єктів;
  • зручнішим для роботи із зовнішніми API, де структура важливіша за ім'я.

7. Але є і ризик

Іноді структурна типізація може призвести до "хибної сумісності":

javascript
interface Cat { name: string; meow(): void; } interface Dog { name: string; bark(): void; } const dog: Dog = { name: "Rex", bark: () => {} }; // @ts-ignore const cat: Cat = dog; // Помилка буде, але логіка схожа cat.meow(); // runtime error!

TypeScript перевірить лише збіг за іменами методів, але не їхню поведінку - це обмеження структурної типізації.


Підсумок

Структурна типізація - це принцип, за яким TypeScript визначає сумісність типів за їхньою формою, а не за ім'ям.

Сумісні - якщо поля і типи збігаються. Несумісні - якщо чогось бракує або тип не збігається.

Це робить TypeScript гнучким, виразним і зручним для JavaScript-екосистеми, де структура об'єктів важливіша за їхнє походження.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.