TypeScript став галузевим стандартом для великомасштабної веб-розробки. Хоча більшість розробників знають основи інтерфейсів і типів, справжня потужність криється в просунутій системі типів. Ось 5 патернів, які виділять вас як старшого інженера.
1. Generic Constraints
Generics потужні, але іноді потрібно обмежити те, що може бути передано. extends - ваш помічник тут.
interface HasId { id: string; } function getById<T extends HasId>(list: T[], id: string): T | undefined { return list.find((item) => item.id === id); }
Забезпечуючи, що T розширює HasId, ми гарантуємо, що доступ до .id всередині функції є безпечним.
2. Conditional Types
Conditional types дозволяють створювати неоднорідні відображення типів. Синтаксис подібний до тернарного оператора в JavaScript.
type IsString<T> = T extends string ? true : false; type A = IsString<string>; // true type B = IsString<number>; // false
Практичний приклад використання - фільтрація типів із union:
type Diff<T, U> = T extends U ? never : T; type NonNullable<T> = Diff<T, null | undefined>;
3. Mapped Types
Mapped types дозволяють створювати нові типи на основі існуючих шляхом трансформації властивостей.
type ReadOnly<T> = { readonly [P in keyof T]: T[P]; }; interface User { name: string; age: number; } type ReadOnlyUser = ReadOnly<User>;
Ви навіть можете додавати або видаляти модифікатори:
type Mutable<T> = { -readonly [P in keyof T]: T[P]; };
4. Template Literal Types
Введені в TypeScript 4.1, вони дозволяють маніпулювати рядковими типами безпосередньо.
type World = 'world'; type Greeting = `hello ${World}`; // "hello world" type Color = 'red' | 'blue'; type Quantity = 'light' | 'dark'; type Palette = `${Quantity}-${Color}`; // "light-red" | "light-blue" | "dark-red" | "dark-blue"
Це неймовірно корисно для типізації рядків, які слідують певному патерну, наприклад CSS-класи або назви подій.
5. Ключове слово infer
Ключове слово infer в conditional types дозволяє витягувати типи з інших типів.
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any; function check(): boolean { return true; } type CheckReturn = ReturnType<typeof check>; // boolean
Тут ми просимо TypeScript "вивести" тип повернення R функції та повернути його.
Висновок
Опанування цих патернів дозволяє писати бібліотеки та утиліти, які є надійними та забезпечують чудовий досвід розробника (DX). Мета просунутого TypeScript - не складність заради складності, а безпека та виразність.