Skip to main content

Чи можна зробити generic-клас?

Що таке generic-клас

Generic-клас - це клас, у якому один або кілька типів (наприклад, T, U, K, V) передаються як параметри, щоб зробити його гнучким і типобезпечним.

Він не прив'язаний до конкретного типу даних, а працює з будь-якими, зберігаючи строгу типізацію.


1. Найпростіший приклад

javascript
class Box<T> { private value: T; constructor(value: T) { this.value = value; } getValue(): T { return this.value; } }

Використання:

javascript
const box1 = new Box<number>(123); const box2 = new Box<string>("Hello"); console.log(box1.getValue()); // 123 console.log(box2.getValue()); // Hello

Тут T - універсальний параметр:

  • при створенні Box<number>T = number,
  • при створенні Box<string>T = string.

TypeScript стежить, щоб тип був узгоджений:

javascript
box1.getValue().toFixed(2); // OK, T = number box2.getValue().toUpperCase(); // OK, T = string

2. Generic-клас з кількома параметрами

javascript
class Pair<K, V> { constructor(public key: K, public value: V) {} describe() { console.log(`Key: ${this.key}, Value: ${this.value}`); } } const pair = new Pair<string, number>("age", 30); pair.describe(); // Key: age, Value: 30

Тут K - тип ключа, V - тип значення. Можна використовувати будь-яку кількість generic-параметрів.


3. Generic-клас з обмеженням (extends)

Можна обмежити тип параметра, щоб він відповідав певній структурі:

javascript
interface Identifiable { id: number; } class Repository<T extends Identifiable> { private items: T[] = []; add(item: T) { this.items.push(item); } findById(id: number): T | undefined { return this.items.find(i => i.id === id); } } const users = new Repository<{ id: number; name: string }>(); users.add({ id: 1, name: "Tim" }); users.add({ id: 2, name: "Alex" }); console.log(users.findById(2)); // { id: 2, name: 'Alex' }

Тут T має бути об'єктом з id: number. Це запобігає помилкам, якщо хтось спробує додати щось без id.


4. Generic-клас з типом за умовчанням

Можна задати тип за умовчанням, якщо його не вказано при створенні:

javascript
class Storage<T = string> { private data: T[] = []; add(item: T) { this.data.push(item); } getAll(): T[] { return this.data; } } const s1 = new Storage(); // T = string (за умовчанням) s1.add("one"); s1.add("two"); const s2 = new Storage<number>(); s2.add(10); s2.add(20);

5. Generic-клас + інтерфейси

Інтерфейси теж можуть бути generic - і класи можуть їх реалізовувати:

javascript
interface IStorage<T> { add(item: T): void; getAll(): T[]; } class ArrayStorage<T> implements IStorage<T> { private data: T[] = []; add(item: T) { this.data.push(item); } getAll(): T[] { return this.data; } }

Так можна створювати "типобезпечні контейнери".


6. Generic-клас з успадкуванням

javascript
class BaseResponse<T> { constructor(public data: T, public success: boolean) {} } class ApiResponse<T> extends BaseResponse<T> { constructor(data: T, public status: number) { super(data, status >= 200 && status < 300); } } const response = new ApiResponse({ id: 1, name: "Tim" }, 200); console.log(response.data.name); // Tim

Дженерики можна успадковувати і передавати далі по ієрархії класів.


Підсумок

МожливістьПрикладОпис
Простий genericclass Box<T> { ... }Типізує вміст
Кілька параметрівclass Pair<K, V>Кілька типів одночасно
Обмеження<T extends SomeType>Обмежує допустимі типи
Тип за умовчанням<T = string>Якщо тип не вказано
Реалізація інтерфейсуclass A<T> implements I<T>Спільно з generic-інтерфейсами
Успадкуванняclass B<T> extends A<T>Дженерики передаються далі

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

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

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