TypeScript

Полезные утилитарные типы

Algonexys · 07.08.2026 · 👁 0

Готовые дженерики для повседневной работы: глубокая частичность, обязательные поля, извлечение типа элемента.

Код

// Рекурсивно делает все поля необязательными
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