TypeScript
Полезные утилитарные типы
Готовые дженерики для повседневной работы: глубокая частичность, обязательные поля, извлечение типа элемента.
Код
// Рекурсивно делает все поля необязательными
type DeepPartial<T> = T extends object
? { [K in keyof T]?: DeepPartial<T[K]> }
: T;
// Делает обязательными только указанные ключи
type RequireKeys<T, K extends keyof T> = T & Required<Pick<T, K>>;
// Ровно один ключ из набора
type ExactlyOne<T, K extends keyof T = keyof T> =
K extends unknown ? Required<Pick<T, K>> & Partial<Record<Exclude<keyof T, K>, never>> : never;
// Тип элемента массива
type ElementOf<T> = T extends readonly (infer U)[] ? U : never;
// Ключи с определённым типом значения
type KeysOfType<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T];
interface Product {
id: number;
title: string;
price: number;
meta: { sku: string; stock: number };
}
type ProductDraft = DeepPartial<Product>;
type WithId = RequireKeys<ProductDraft, 'id'>;
type NumericFields = KeysOfType<Product, number>; // 'id' | 'price'
type Item = ElementOf<Product[]>; // Product