TypeScriptのユーティリティ型(Partial・Pick・Omit・ReturnTypeなど)を整理した話
TypeScriptには型を変換・加工するユーティリティ型が組み込まれています。SvelteKitのコードでも頻繁に使います。
① Partial — 全プロパティを省略可能にする
type Post = {
id: number;
title: string;
body: string;
};
type PartialPost = Partial<Post>;
// { id?: number; title?: string; body?: string; }
実務での使い場面: 更新フォームで「変更したフィールドだけ送る」とき。
async function updatePost(id: number, updates: Partial<Post>) {
// title だけ・body だけの更新が可能
}
② Required — 全プロパティを必須にする
type DraftPost = {
title?: string;
body?: string;
};
type PublishedPost = Required<DraftPost>;
// { title: string; body: string; }
③ Pick — 特定のプロパティだけ抽出する
type Post = {
id: number;
title: string;
body: string;
};
// 一覧表示用(body は不要)
type PostSummary = Pick<Post, 'id' | 'title'>;
// { id: number; title: string; }
実務での使い場面: 一覧APIでは全フィールドを返さず必要なものだけに絞るとき。
// SELECT id, title FROM posts → PostSummary 型で受け取る
const result = await db.prepare('SELECT id, title FROM posts')
.all<PostSummary>();
④ Omit — 特定のプロパティを除外する
// 新規作成フォーム用(id は自動採番なので不要)
type NewPost = Omit<Post, 'id'>;
// { title: string; body: string; }
// 更新フォーム用(id は変更不要 + 変更したいフィールドだけ送る)
type UpdatePost = Partial<Omit<Post, 'id'>>;
// { title?: string; body?: string; }
Pick の逆です。「これ以外を残したい」ときは Omit が便利です。
⑤ ReturnType — 関数の戻り値の型を取得する
function createUser() {
return {
id: crypto.randomUUID(),
name: 'ゲスト',
createdAt: new Date(),
};
}
type User = ReturnType<typeof createUser>;
// { id: string; name: string; createdAt: Date; }
実務での使い場面: load 関数の戻り値の型を使い回すとき。
// +page.server.ts の load の戻り値を型として使う
type PageData = Awaited<ReturnType<typeof load>>;
⑥ Awaited — Promiseの中の型を取り出す
type Result = Awaited<Promise<string>>;
// string
async function fetchPost() {
return { id: 1, title: '記事' };
}
type Post = Awaited<ReturnType<typeof fetchPost>>;
// { id: number; title: string; }
ReturnType と組み合わせて、async関数の戻り値の型を取り出すときによく使います。
⑦ Record — キーと値の型を指定したオブジェクト型
// キーが string、値が number のオブジェクト
type ScoreMap = Record<string, number>;
// { [key: string]: number }
// キーを列挙型に限定する
type CategoryCount = Record<'tech' | 'life' | 'work', number>;
// { tech: number; life: number; work: number; }
SvelteKitでよく使う組み合わせ
// src/lib/posts.ts
export type Post = {
id: number;
title: string;
body: string;
};
// 新規作成フォーム用(id は自動採番なので不要)
export type NewPost = Omit<Post, 'id'>;
// 更新フォーム用(変更したいフィールドだけ送れるように)
export type UpdatePost = Partial<Omit<Post, 'id'>>;
// 一覧表示用(body は不要)
export type PostSummary = Pick<Post, 'id' | 'title'>;
元の型から派生した型を作ることで、Post の定義を変えたときに派生型も自動で追従します。
型が効いているかの確認方法
エディタ上でエラーが出ることで型が正しく効いているか確認できます。
const body = await request.json() as NewPost;
// ❌ NewPost に id は存在しないのでTypeScriptエラーになる
console.log(body.id);
// ✅ これはOK
console.log(body.title);
console.log(body.body);
まとめ
| ユーティリティ型 | 内容 | 使い場面 |
|---|---|---|
Partial<T> |
全プロパティを省略可能に | 更新フォーム |
Required<T> |
全プロパティを必須に | 省略可能な型を確定させる |
Pick<T, K> |
特定のプロパティだけ抽出 | 一覧表示・フォーム |
Omit<T, K> |
特定のプロパティを除外 | 新規作成フォーム |
ReturnType<T> |
関数の戻り値の型を取得 | load関数の戻り値 |
Awaited<T> |
Promiseの中の型を取り出す | async関数と組み合わせて |
Record<K, V> |
キーと値の型を指定したオブジェクト | マップ型のデータ |