← Назад к вопросам

Для чего нужен Omit?

1.0 Junior🔥 181 комментариев
#TypeScript

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

TypeScript Omit: исключение свойств из типов

Что такое Omit?

Omit — это встроенный утилитарный тип TypeScript, который создаёт новый тип на основе существующего, но исключает указанные свойства. Это противоположность Pick, который наоборот берёт только нужные свойства.

Синтаксис:

type NewType = Omit<OriginalType, "propertyName1" | "propertyName2">;

Практические примеры

Пример 1: Исключение чувствительных данных

interface User {
  id: string;
  name: string;
  email: string;
  password: string;
  createdAt: Date;
}

// Тип для отправки клиенту (без пароля)
type PublicUser = Omit<User, "password">;

// PublicUser имеет структуру:
// { id: string; name: string; email: string; createdAt: Date; }

const user: PublicUser = {
  id: "123",
  name: "John",
  email: "john@example.com",
  createdAt: new Date(),
  // password: "..." // ❌ Error: не может быть использовано
};

Пример 2: Исключение нескольких полей

interface BlogPost {
  id: string;
  title: string;
  content: string;
  author: string;
  createdAt: Date;
  updatedAt: Date;
  views: number;
  comments: Comment[];
}

// Тип для отправки на API (без служебных полей)
type CreatePostRequest = Omit<BlogPost, "id" | "createdAt" | "updatedAt" | "views" | "comments">;

// CreatePostRequest = { title: string; content: string; author: string; }

async function createPost(payload: CreatePostRequest) {
  const response = await fetch("/api/posts", {
    method: "POST",
    body: JSON.stringify(payload),
  });
  return response.json();
}

Пример 3: Наследование с исключением

interface BaseComponent {
  id: string;
  className?: string;
  onClick?: () => void;
  disabled?: boolean;
  data?: Record<string, any>;
}

// Компонент Button без некоторых полей
interface ButtonProps extends Omit<BaseComponent, "data"> {
  label: string;
  variant?: "primary" | "secondary";
}

const Button: React.FC<ButtonProps> = ({
  id,
  className,
  onClick,
  disabled,
  label,
  variant = "primary",
}) => {
  return (
    <button
      id={id}
      className={className}
      onClick={onClick}
      disabled={disabled}
    >
      {label}
    </button>
  );
};

Пример 4: Обновление в базе данных

interface Product {
  id: string;
  name: string;
  description: string;
  price: number;
  stock: number;
  createdAt: Date;
  updatedAt: Date;
  createdBy: string;
}

// Для обновления продукта: исключаем id и служебные поля
type UpdateProductRequest = Omit<Product, "id" | "createdAt" | "updatedAt" | "createdBy">;

async function updateProduct(id: string, payload: UpdateProductRequest) {
  const response = await fetch(`/api/products/${id}`, {
    method: "PATCH",
    body: JSON.stringify(payload),
  });
  return response.json();
}

// Использование
updateProduct("123", {
  name: "New Name",
  description: "New Description",
  price: 99.99,
  stock: 50,
  // id, createdAt, updatedAt, createdBy — не требуются
});

Пример 5: React компонент с Omit

interface HTMLInputProps
  extends React.InputHTMLAttributes<HTMLInputElement> {}

interface CustomInputProps extends Omit<HTMLInputProps, "onChange" | "onBlur"> {
  onChange?: (value: string) => void;
  onBlur?: (value: string) => void;
  label?: string;
  error?: string;
}

const CustomInput: React.FC<CustomInputProps> = ({
  label,
  error,
  onChange,
  onBlur,
  ...rest
}) => {
  return (
    <div>
      {label && <label>{label}</label>}
      <input
        {...rest}
        onChange={(e) => onChange?.(e.target.value)}
        onBlur={(e) => onBlur?.(e.target.value)}
      />
      {error && <span className="error">{error}</span>}
    </div>
  );
};

Omit vs Pick

interface User {
  id: string;
  name: string;
  email: string;
  age: number;
}

// Pick: берёт только указанные свойства
type UserPreview = Pick<User, "name" | "email">;
// { name: string; email: string; }

// Omit: исключает указанные свойства
type UserWithoutEmail = Omit<User, "email">;
// { id: string; name: string; age: number; }

Когда использовать Omit?

Используй Omit когда:

  • Нужно исключить чувствительные данные (пароли, токены)
  • Разные версии одного типа для разных операций (create, update, view)
  • Наследуешь типы и хочешь переопределить некоторые поля
  • Работаешь с API и нужны разные типы запросов/ответов

Не используй Omit если:

  • Исключаемых свойств больше половины (используй Pick)
  • Часто меняется список исключаемых свойств (сделай явный интерфейс)
  • Нужна полная типизация (явный интерфейс лучше читается)

Продвинутые примеры

Исключение множественных типов:

interface Config {
  apiUrl: string;
  timeout: number;
  retries: number;
  debug: boolean;
  logger: Logger;
  cache: CacheManager;
}

// Для клиента отправляем только строковые и числовые конфиги
type ClientConfig = Omit<Config, "logger" | "cache">;

Комбинирование с другими утилитами:

interface Form {
  id: string;
  name: string;
  fields: Field[];
  createdAt: Date;
  updatedAt: Date;
}

// Исключаем временные метки и делаем всё опциональным
type PartialFormUpdate = Partial<Omit<Form, "createdAt" | "updatedAt">>;

const formUpdate: PartialFormUpdate = {
  name: "New Form",
  // остальное опционально
};

Заключение

Omit — это мощный утилитарный тип, который помогает создавать чистые и безопасные типы данных. Используй его для исключения чувствительных данных, служебных полей и для создания разных версий одного типа для разных операций. Это делает код более типобезопасным и читаемым.

Для чего нужен Omit? | PrepBro