Що означає "структурна типізація"?
1. Суть структурної типізації
Структурна типізація означає, що два типи вважаються сумісними, якщо у них однакова структура (тобто однаковий набір властивостей та їх типів), навіть якщо вони були оголошені по-різному.
Іншими словами: TypeScript дивиться не на ім'я типу, а на його форму (shape).
Приклад
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):
class User { int id; String name; }
class Person { int id; String name; }
// User та Person несумісні, навіть якщо поля однаковіА у TypeScript:
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. Приклад несумісності
Якщо бракує хоча б однієї властивості або тип відрізняється - несумісно:
interface User {
id: number;
name: string;
}
const invalid = { id: "1", name: "Tim" }; // id не число
let u: User = invalid; // Помилка: id має бути number4. Як TypeScript перевіряє сумісність
TypeScript йде "за структурою" об'єкта:
- Дивиться на всі обов'язкові поля цільового типу.
- Перевіряє, що у переданого значення є ті самі поля з сумісними типами.
- Ігнорує зайві властивості (якщо вони не заважають контексту).
5. Приклад зі складними структурами
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. Але є і ризик
Іноді структурна типізація може призвести до "хибної сумісності":
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-екосистеми, де структура об'єктів важливіша за їхнє походження.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.