Пиши переиспользуемые функции и типы, которые сохраняют полную точность типов при каждом вызове.
Открыть этот урок в KodokonТы уже пользуешься обобщениями, сам того не замечая: string[], Promise<number>... Пора написать свои. Обобщение вводит параметр типа - переменную, которую при каждом использовании заменяет конкретный тип. Цель: написать логику один раз, не жертвуя точностью типов.
function first<T>(items: T[]): T | undefined {
return items[0];
}
const n = first([10, 20, 30]);
const s = first(["a", "b"]);Заметь, что при вызове ты ничего не указал: TypeScript выводит T из аргумента. Обобщение без ограничений принимает что угодно, но функции часто нужен минимум гарантий о своих данных. Ключевое слово extends задаёт для T минимальную форму.
interface HasId {
id: number;
}
function findById<T extends HasId>(
items: T[],
id: number
): T | undefined {
return items.find((item) => item.id === id);
}Сами типы тоже могут быть обобщёнными. Это повседневность в сетевом коде: структура ответа стабильна, меняется лишь содержимое data. Один-единственный тип описывает тогда все ответы твоего API.
interface ApiResponse<T> {
ok: boolean;
data: T;
}
type UserResponse = ApiResponse<{ name: string }>;
const res: UserResponse = {
ok: true,
data: { name: "Ada" },
};