TypeScript Advanced Generics пояснюється на прикладах
Generics у TypeScript надають можливість створювати повторно використовувані та гнучкі компоненти коду, працюючи з різними типами даних. Розширені генерики розвивають цю концепцію, додаючи додаткові функції, такі як обмеження, значення за замовчуванням і кілька типів, що дозволяє розробникам писати більш надійний і безпечний код. У цій статті будуть використані приклади для вивчення цих розширених концепцій у генериках.
Загальні обмеження
Обмеження обмежують типи, які може приймати універсал. Це гарантує, що тип, переданий у загальну функцію або клас, відповідає певним критеріям. Наприклад, обмеження можна використовувати, щоб гарантувати, що загальний тип має певну властивість або метод.
function getLength<T extends { length: number }>(arg: T): number {
return arg.length;
}
const stringLength = getLength("TypeScript");
const arrayLength = getLength([1, 2, 3]);
У цьому прикладі обмеження <T extends { length: number }>
гарантує, що аргумент, переданий getLength
, має властивість length
.
Кілька дженериків
TypeScript дозволяє використовувати кілька загальних типів в одній функції, класі або інтерфейсі. Це корисно під час роботи з парами значень або іншими структурами даних, що містять кілька типів.
function pair<T, U>(first: T, second: U): [T, U] {
return [first, second];
}
const stringNumberPair = pair("TypeScript", 2024);
Ця функція, pair
, приймає два різні загальні типи, T
і U
, і повертає кортеж, що містить обидва типи.
Загальні типи за замовчуванням
Генерики у TypeScript також можуть мати типові типи. Це корисно, якщо ви хочете, щоб загальний тип мав запасний тип, якщо не надано конкретного типу.
function identity<T = string>(value: T): T {
return value;
}
const defaultString = identity("Hello"); // T is string
const customNumber = identity<number>(100); // T is number
У цьому прикладі, якщо до identity
не передано тип, за замовчуванням буде string
.
Використання Generics з інтерфейсами
Генерики можна використовувати з інтерфейсами для визначення складних структур, де типи не є фіксованими. Це додає гнучкості в управлінні даними.
interface Container<T> {
value: T;
}
const stringContainer: Container<string> = { value: "Hello" };
const numberContainer: Container<number> = { value: 42 };
Інтерфейс Container
призначений для зберігання значення будь-якого типу, дозволяючи різні типи контейнерів із певними типами.
Загальні класи
Класи в TypeScript також можуть бути загальними. Це особливо корисно при розробці класів, які працюють з різними типами даних, наприклад, класи зберігання даних або колекції.
class DataStore<T> {
private data: T[] = [];
add(item: T): void {
this.data.push(item);
}
getAll(): T[] {
return this.data;
}
}
const stringStore = new DataStore<string>();
stringStore.add("Hello");
stringStore.add("TypeScript");
const numberStore = new DataStore<number>();
numberStore.add(42);
У цьому прикладі клас DataStore
працює з будь-якими типами даних, надаючи безпечний спосіб зберігання та отримання елементів.
Висновок
Розширені генерики в TypeScript є потужним інструментом для написання гнучкого, багаторазового та безпечного коду. Використовуючи обмеження, кілька типів, значення за замовчуванням і загальні засоби в класах та інтерфейсах, розробники можуть писати більш складний і надійний код. Розуміння та використання цих передових концепцій забезпечує більшу гнучкість і забезпечує безпеку типів у різних програмах.