Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «structural typing в інтерфейсах». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Structural typing** - це принцип, за яким сумісність типів визначається за їхньою формою (структурою), а не за іменем типу. **Ключове:** якщо об'єкт містить усі необхідні властивості потрібних типів, він вважається сумісним з інтерфейсом, навіть якщо не оголошений як цей тип.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 1. Що таке structural typing (структурна типізація) > **Structural typing** - це принцип, за яким > сумісність типів визначається **за їхньою формою (структурою)**, > а не за іменем типу. Простіше кажучи: > якщо об'єкт **виглядає** як інтерфейс, > TypeScript вважає, що він **відповідає цьому інтерфейсу**. --- ### Приклад ```javascript interface User { id: number; name: string; } const person = { id: 1, name: "Tim", age: 25, }; // Можна присвоїти - структура збігається const u: User = person; ``` > Хоча `person` **не оголошений як** `User`, > TypeScript бачить, що в нього **є всі потрібні поля** (`id` і `name`), > і вважає типи сумісними. > > Зайві поля (`age`) не заважають. --- ## 2. На відміну від номінальної типізації (nominal typing) У деяких мовах (наприклад, Java, C#, Swift) сумісність типів перевіряється **за іменем** або **за декларацією**, а не за структурою. ### Приклад (як було б за nominal typing): ```javascript class User { int id; String name; } class Person { int id; String name; } // Помилка - типи різні, хоча поля однакові User u = new Person(); ``` > У TypeScript навпаки - **головне, щоб структура збігалася**. > І це робить мову гнучкішою та "утилітарнішою". --- ## 3. Як TypeScript перевіряє сумісність структур TypeScript порівнює **форму об'єктів**, а не їхнє "походження". ### Приклад: ```javascript interface Point { x: number; y: number; } const coord = { x: 10, y: 20, z: 30 }; const p: Point = coord; // OK ``` > Перевіряється: > "Чи є в `coord` властивості `x` та `y` потрібних типів?" - > Так -> отже, він відповідає `Point`. --- ## 4. Структурна типізація працює і з функціями ```javascript interface Logger { (msg: string): void; } function logToConsole(message: string) { console.log(message); } const logger: Logger = logToConsole; // OK ``` > TypeScript перевіряє **сигнатуру функції**, > а не те, як вона названа. --- ## 5. Чому це важливо Завдяки структурній типізації: - можна використовувати **інлайн-об'єкти** без явних інтерфейсів; - типи стають **гнучкими та сумісними**; - легко працювати із **зовнішніми даними (API, JSON)**; - зменшується кількість "церемоній" (менше boilerplate-коду). --- ## Приклад: "качина типізація" (duck typing) > "Якщо щось **крякає як качка** і **виглядає як качка**, > TypeScript вважає, що це **качка**." ```javascript interface Duck { quack(): void; } const animal = { quack: () => console.log("Quack!"), }; const d: Duck = animal; // OK - структура збігається ``` --- ## 6. Як structural typing впливає на інтерфейси Інтерфейси в TypeScript: - **не є реальними сутностями під час виконання**; - **визначають лише форму даних**; - працюють **за принципом структурної відповідності**. ### Приклад: ```javascript interface Car { wheels: number; } interface Truck { wheels: number; } let c: Car = { wheels: 4 }; let t: Truck = c; // OK - структура збігається ``` > Хоча `Car` і `Truck` - різні інтерфейси, > TypeScript вважає їх сумісними, > тому що вони мають однакову структуру. --- ## 7. Коли це може бути неочікуваним Іноді структурна типізація призводить до "надто гнучкої" поведінки: ```javascript interface Point2D { x: number; y: number; } interface Point3D { x: number; y: number; z: number; } const point3D: Point3D = { x: 1, y: 2, z: 3 }; const p2d: Point2D = point3D; // OK ``` > TypeScript не проти - адже в `point3D` є все, що потрібно `Point2D`. > Але це може призвести до логічних помилок, якщо ти очікував 2D-точку. --- ## 8. Structural typing і класи Класи теж структурно типізовані. Тобто неважливо, "від чого" вони успадковуються - важливо, **що в них є**. ```javascript class Person { name = "Tim"; } interface Named { name: string; } let p: Named = new Person(); // OK - поля збігаються ``` > Навіть якщо `Person` не "реалізує" інтерфейс `Named`, > він все одно сумісний з ним. --- ## Підсумок > **Structural typing** - це спосіб перевірки типів у TypeScript, > за якого сумісність визначається **за структурою**, а не за іменем. > > Тобто: > якщо об'єкт *містить усі необхідні властивості* потрібних типів, > він **вважається сумісним** з інтерфейсом. > > Переваги: > > - гнучкість і зручність при роботі з даними; > - менше коду (не потрібно явно "implements" все підряд); > - ідеально підходить для JSON, API, функцій та об'єктів. > > Мінус: > > - можна випадково передати "зайві" дані і не помітити невідповідності логіки.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.