Skip to main content

Типізація заради типізації

Що означає "типізація заради типізації"

Це коли розробник додає або ускладнює типи, не вирішуючи реальних проблем, просто щоб "усе було типізовано".

Простіше кажучи:

"Типи заради галочки", а не заради розуміння, захисту та читабельності коду.


Приклади "типізації заради типізації"

1. Типи, які нічого не додають

javascript
const name: string = "Alex"; // надлишково

TypeScript і так виведе тип string - ти просто повторив очевидне.

Краще:

javascript
const name = "Alex";

2. Дублювання структури без сенсу

javascript
type User = { id: number; name: string; }; function getUser(): { id: number; name: string } { // типи продубльовані return { id: 1, name: "Tom" }; }

Краще:

javascript
function getUser(): User { return { id: 1, name: "Tom" }; }

3. Надлишкові generics

javascript
function identity<T>(value: T): T { // ок, базовий приклад return value; } function double<T extends number>(x: T): number { // generic марний return x * 2; }

Тут T не несе жодної цінності. Простіше:

javascript
function double(x: number): number { return x * 2; }

4. Перетипізація без потреби

javascript
const user = { name: "John" } as { name: string }; // марно

TypeScript і так розуміє, що це { name: string }.


5. Занадто глибока типізація даних

javascript
type Config = { features: { flags: { experimental: { alphaMode: boolean; betaUI: boolean; }; }; }; };

Звучить "строго", але часто простіше описати частково:

javascript
type Config = Record<string, any>; // або Partial<Record<string, boolean>>

Типізація має відображати суть, а не структуру документації.


Чому це антипатерн

1. Втрата гнучкості

Надмірна типізація заважає працювати з реальними, мінливими даними.

Приклад:

javascript
type User = { id: number; name: string; age: number }; function updateUser(user: User) { user.id = 123; // ok user.nickname = "coolguy"; // не можна, навіть якщо API реально повертає це поле }

Код став надто жорстким - замість захисту ти отримав "кам'яні стіни".


2. Збільшення складності коду без вигоди

Іноді розробники роблять "типову математику", щоб вивести ідеально точний тип, який ніхто потім не може зрозуміти.

Приклад:

javascript
type Flatten<T> = T extends (infer U)[] ? U : T; type DeepPartial<T> = { [K in keyof T]?: DeepPartial<T[K]> };

Це красиво і корисно в бібліотеці, але у звичайному застосунку - надлишково і знижує читабельність.


3. Менше користі, більше шуму

Часто типи починають заважати, а не допомагати:

javascript
function sum(a: number, b: number): number { return a + b; }

Це коректно, але якщо таких декларацій 1000, код стає "шумним", а IDE вже й так підказує типи з контексту.


4. Хибне відчуття безпеки

"Типізація заради типізації" створює ілюзію, що все безпечно, але насправді може бути не так.

Приклад:

javascript
interface User { id: number; name: string; } const user = {} as User; // обман TypeScript console.log(user.name.toUpperCase()); // runtime crash

Типи є, помилок немає, але програма все одно впаде. Типізація не дорівнює валідації даних.


5. Складніше рефакторити та підтримувати

Коли типи занадто деталізовані або надлишкові, кожна зміна коду вимагає каскадних правок типів.

Приклад:

javascript
type Product = { id: number; title: string; price: number }; type ProductResponse = { data: { items: Product[] }; meta: { total: number } };

Якщо API змінило структуру, доводиться правити десятки типів, навіть якщо логіка коду не змінилася.


6. Продуктивність компіляції падає

TypeScript компілює і перевіряє всі типи, включно з непотрібними та штучно ускладненими. У великих проєктах це реально сповільнює збірку.

Особливо якщо ти використовуєш складні conditional types та infer без потреби.


7. Порушення принципу "типізація не дорівнює логіка"

Деякі розробники починають "ховати бізнес-логіку в типах":

Приклад:

javascript
type Access<T extends Role> = T extends "admin" ? AdminPanel : T extends "user" ? UserDashboard : GuestPage;

Виглядає розумно, але:

  • складніше зрозуміти;
  • IDE втрачає підказки;
  • а логіка має бути в коді, а не в типах.

Як зрозуміти, що ти в пастці "типізації заради типізації"

Ось "чеклист" симптомів:

СимптомОзнака антипатерну
Ти пишеш тип, який TS міг би вивести самнадлишково
У тебе з'являється більше коду типів, ніж логікиперевантаження
Тобі доводиться часто писати asтипова модель недосконала
Типи виглядають як "математика" і їх важко читатиускладнення
Кожен рефакторинг ламає 20 типівпереінженерія
Тобі хочеться додати "ще один generic для краси"тривожний дзвіночок

Правильний підхід: прагматична типізація

Типізація має вирішувати задачу, а не доводити, що ти знаєш TypeScript.

Принципи:

  1. Типізуй інтерфейси взаємодії, а не деталі реалізації. (входи/виходи функцій, API, контракти між модулями)
  2. Довіряй виведенню типів TS - не пиши :string, якщо компілятор і так знає.
  3. Використовуй as const, ReturnType<>, typeof, щоб не дублювати типи.
  4. Спочатку код, потім тип - не будуй типову систему "попереду коду".
  5. Не соромся any чи unknown локально, якщо це прискорить розробку - головне, щоб інтерфейси залишилися строгими.
  6. Чим ближче тип до бізнес-логіки, тим простішим він має бути.

Приклад "хорошої типізації"

javascript
function fetchUser(id: number) { return fetch(`/api/users/${id}`) .then(res => res.json() as Promise<{ id: number; name: string }>); }

Тип описує контракт функції, а не кожен проміжний крок. Він короткий, зрозумілий і захищає від реальних помилок.


Підсумок

ПитанняВідповідь
Що таке "типізація заради типізації"?Надлишковий або беззмістовний опис типів, що не приносить реальної користі
Чому це антипатерн?Ускладнює код, сповільнює збірку, створює хибну безпеку та заважає розвитку проєкту
Як зрозуміти, що ти в пастці?Типів більше, ніж логіки, часті as, все ламається при найменшій зміні
Як правильно?Типізувати інтерфейси та межі модулів, а не внутрішні деталі, використовувати виведення типів

Простими словами:

Хороша типізація - як страховка: вона захищає від реальних ризиків, а не навішує 20 ременів на один велосипед.

TypeScript - про сенс, не про синтаксис.

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

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

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