TypeScript предлагает широкий спектр инструментов для создания типобезопасного и эффективного кода. Одним из наиболее мощных инструментов в этом арсенале являются generics, которые позволяют писать многократно используемый код без дублирования функций или использования неопределенных типов.
Основные Концепции
Чтобы начать работу с generics, необходимо понять их основную идею. Generics позволяют функциям и классам работать с различными типами данных, не теряя типобезопасности. Например, функция, которая возвращает первый элемент массива, может быть определена с использованием generics:
function getFirst<T>(items: T[]): T | undefined {
return items[0];
}
Это определение гарантирует, что функция getFirst может быть использована с массивами любого типа, но при этом обеспечивает типобезопасность, поскольку TypeScript может определить тип возвращаемого значения на основе типа массива.
Generic API Ответы
Generics особенно полезны при работе с API, где ответы могут иметь различные структуры и типы данных. Например, можно определить интерфейс ApiResponse, который использует generics для описания типа данных в ответе:
interface ApiResponse<T> {
data: T;
meta: {
page: number;
total: number;
};
}
Этот интерфейс можно использовать для определения функций, которые выполняют запросы к API и возвращают ответы с типобезопасными данными:
async function fetchPaginated<T>(url: string): Promise<ApiResponse<T>> {
return (await fetch(url)).json();
}
Generic Репозиторий
Generics также могут быть использованы для создания классов, которые работают с различными типами данных. Например, можно определить класс Repository, который использует generics для описания типа данных, с которым он работает:
class Repository<T extends HasId> {
constructor(private collection: string) {}
async findById(id: string): Promise<T | null> {
return db.collection(this.collection).findOne({ id });
}
async create(data: Omit<T, "id">): Promise<T> {
const doc = { ...data, id: randomUUID() } as T;
await db.collection(this.collection).insertOne(doc);
return doc;
}
}
Этот класс можно использовать для создания репозиториев, которые работают с различными типами данных, обеспечивая при этом типобезопасность и многократное использование кода.
Утилитные Типы
TypeScript предлагает ряд утилитных типов, которые могут быть использованы в сочетании с generics для создания ещё более мощных и гибких инструментов. Например, можно использовать типы Partial, Pick, Omit и Record для манипуляции типами данных и создания новых типов на основе существующих. Эти типы могут быть особенно полезны при работе с generics и создании типобезопасных и эффективных решений для задач бэкенда.