Код IT
← Каталог

Справочник по TypeScript — Комбо-паттерн: безопасное обновление полей модели

Фрагмент из «Справочник по TypeScript»: Комбо-паттерн: безопасное обновление полей модели.

typescript javascriptencyclopedia301 embed URL статья в энциклопедии
TypeScript main.ts
type Visibility = 'draft' | 'active' | 'archived' | 'out_of_stock';

interface Product {
  readonly id: string;
  price: number;
  stock: number;
  visibility: Visibility;
}

type Updatable<T> = Omit<T, 'id'>;

type SafeUpdate<T> = <K extends keyof Updatable<T>>(
  key: K,
  value: Updatable<T>[K]
) => T;

const createUpdater =
  <T,>(entity: T): SafeUpdate<T> =>
  (key, value) => ({ ...entity, [key]: value });

const product: Product = {
  id: 'prod_001',
  price: 100,
  stock: 10,
  visibility: 'draft'
};

const updateProduct = createUpdater(product);

updateProduct('price', 120);         // OK
updateProduct('visibility', 'active'); // OK

// updateProduct('id', 'prod_002');      // Ошибка: ключ исключён
// updateProduct('stock', '100');        // Ошибка: string не number
// updateProduct('visibility', 'deleted'); // Ошибка: нет в union
type Visibility = 'draft' | 'active' | 'archived' | 'out_of_stock';

interface Product {
  readonly id: string;
  price: number;
  stock: number;
  visibility: Visibility;
}

type Updatable<T> = Omit<T, 'id'>;

type SafeUpdate<T> = <K extends keyof Updatable<T>>(
  key: K,
  value: Updatable<T>[K]
) => T;

const createUpdater =
  <T,>(entity: T): SafeUpdate<T> =>
  (key, value) => ({ ...entity, [key]: value });

const product: Product = {
  id: 'prod_001',
  price: 100,
  stock: 10,
  visibility: 'draft'
};

const updateProduct = createUpdater(product);

updateProduct('price', 120);         // OK
updateProduct('visibility', 'active'); // OK

// updateProduct('id', 'prod_002');      // Ошибка: ключ исключён
// updateProduct('stock', '100');        // Ошибка: string не number
// updateProduct('visibility', 'deleted'); // Ошибка: нет в union