📘
OmitとPickの使い分け、迷うことあるよね。

はじめに
最近、TypeScriptの型定義を見直していて気づいたことがあります。Omit と Pick、どっちを使うべきか迷う場面って意外と多いんですよね。
「どっちでも書けるけど、どっちが良いの?」という疑問に答えます。
結論:除外するプロパティが少ない方を使う
type User = {
id: number
name: string
email: string
password: string
createdAt: Date
updatedAt: Date
}
// パターン1: Pick(必要なものだけ選ぶ)
type UserResponse = Pick<User, 'id' | 'name' | 'email'>
// パターン2: Omit(不要なものを除外)
type UserResponse = Omit<User, 'password' | 'createdAt' | 'updatedAt'>
どちらも同じ結果になりますが、除外する項目が少ない方が読みやすいです。
判断基準:元の型に対する「割合」
ケース1: 大部分を使う → Omit
type Product = {
id: number
name: string
price: number
description: string
stock: number
categoryId: number
createdAt: Date
updatedAt: Date
}
// ❌ Pick だと長い
type CreateProductInput = Pick<Product, 'name' | 'price' | 'description' | 'stock' | 'categoryId'>
// ✅ Omit の方が短い
type CreateProductInput = Omit<Product, 'id' | 'createdAt' | 'updatedAt'>
8個中3個除外 → Omit が適切
ケース2: 一部だけ使う → Pick
type Article = {
id: number
title: string
body: string
authorId: number
categoryId: number
tags: string[]
viewCount: number
likeCount: number
publishedAt: Date
createdAt: Date
updatedAt: Date
}
// ❌ Omit だと長い
type ArticleCard = Omit<Article, 'body' | 'authorId' | 'categoryId' | 'tags' | 'viewCount' | 'likeCount' | 'publishedAt' | 'createdAt' | 'updatedAt'>
// ✅ Pick の方が短い
type ArticleCard = Pick<Article, 'id' | 'title'>
11個中2個使用 → Pick が適切
実務でよくあるパターン
パターン1: API レスポンス型(Omit)
type User = {
id: number
name: string
email: string
password: string // ← 外部に出してはいけない
salt: string // ← 外部に出してはいけない
}
// ✅ セキュリティ的に除外すべきものを明示
type UserResponse = Omit<User, 'password' | 'salt'>
意図: 「password と salt は外に出さない」を明示
パターン2: フォーム入力型(Pick)
type User = {
id: number
name: string
email: string
role: 'admin' | 'user'
createdAt: Date
updatedAt: Date
}
// ✅ ユーザーが入力できる項目だけを明示
type UserFormInput = Pick<User, 'name' | 'email'>
意図: 「name と email だけ入力できる」を明示
パターン3: 更新用型(両方使う)
type Product = {
id: number
name: string
price: number
createdAt: Date
updatedAt: Date
}
// id は必須、タイムスタンプは除外、他は optional
type UpdateProductInput = Partial<Omit<Product, 'createdAt' | 'updatedAt'>> & Pick<Product, 'id'>
// 結果: { id: number; name?: string; price?: number }
実務での頻出パターン:PATCH リクエストの型定義
重要:拡張性の違い
実はOmit の方が拡張性が高いです。
元の型にプロパティが追加された時の挙動
// 最初の User 型
type User = {
id: number
name: string
email: string
}
// ❌ Pick: 新しいプロパティは自動で含まれない
type UserResponse = Pick<User, 'id' | 'name' | 'email'>
// ✅ Omit: 新しいプロパティは自動で含まれる
type UserResponse = Omit<User, 'password'>
後から User に age: number を追加したとします:
type User = {
id: number
name: string
email: string
age: number // ← 追加
}
// Pick: age は含まれない(明示的に追加が必要)
type UserResponse = Pick<User, 'id' | 'name' | 'email'>
// → { id: number; name: string; email: string }
// Omit: age は自動で含まれる
type UserResponse = Omit<User, 'password'>
// → { id: number; name: string; email: string; age: number }
実務での判断
// ケース1: セキュリティで除外する項目が決まっている → Omit
type UserResponse = Omit<User, 'password' | 'salt'>
// User に新しいプロパティが増えても、password/salt 以外は全部レスポンスに含まれる
// ケース2: フォームで入力できる項目が決まっている → Pick
type UserFormInput = Pick<User, 'name' | 'email'>
// User に新しいプロパティが増えても、フォームでは name/email だけ入力可能
拡張性を考えると Omit の方が有利ですが、意図的に制限したい場合は Pickを使います。
迷った時の判断フロー
1. 拡張性を考える(最重要)
→ 将来プロパティが増えそう & 自動で含めたい:Omit
→ 項目を厳密に制限したい:Pick
2. 元の型に対して「使う項目」は何割?
→ 5割以上:Omit(不要なものを除外)
→ 5割未満:Pick(必要なものを選択)
3. 意図を明示したい場合
→ セキュリティ:Omit(「これは出さない」を明示)
→ 入力制限:Pick(「これだけ許可」を明示)
4. どっちでも同じなら
→ 短い方を選ぶ
よくある間違い
間違い1: 無理に Omit を使う
type Config = {
apiUrl: string
timeout: number
retryCount: number
debug: boolean
logLevel: 'info' | 'warn' | 'error'
}
// ❌ 長い
type MinimalConfig = Omit<Config, 'timeout' | 'retryCount' | 'debug' | 'logLevel'>
// ✅ 短い
type MinimalConfig = Pick<Config, 'apiUrl'>
間違い2: 型安全性を失う
type User = {
id: number
name: string
email: string
age: number
}
// ❌ age を追加したら UserResponse に漏れる
type UserResponse = Omit<User, 'password'> // password は元々ない
// ✅ 意図が明確
type UserResponse = Pick<User, 'id' | 'name' | 'email'>
Omit は「元の型にあるもの」しか除外できないので注意。
まとめ
| Omit | Pick | |
|---|---|---|
| 使い時 | 大部分を使う時 | 一部だけ使う時 |
| 意図 | 「これは出さない」 | 「これだけ許可」 |
| 実務例 | API レスポンス(秘匿情報除外) | フォーム入力(入力項目限定) |
迷ったら「短い方」を選ぶでOKです👍
おまけ: 組み合わせパターン
実務でよく使う組み合わせ:
// パターン1: Omit + Partial(更新用)
type UpdateInput = Partial<Omit<User, 'id' | 'createdAt'>>
// パターン2: Pick + Required(必須化)
type LoginInput = Required<Pick<User, 'email' | 'password'>>
// パターン3: Omit + Pick(複雑な条件)
type FormData = Partial<Omit<User, 'createdAt' | 'updatedAt'>> & Pick<User, 'id'>
慣れてきたら、こういう組み合わせもサクッと書けるようになります。
Discussion