ユーティリティ型
11.3.1. 基本ユーティリティ型
TypeScript 組み込みユーティリティ型を積極的に活用して、型の重複を防止します。
| ユーティリティ型 | 用途 | 説明 |
|---|---|---|
Partial<T> | 編集フォーム | すべてのプロパティをオプショナルに変換 |
Required<T> | 必須保証 | すべてのプロパティを必須に変換 |
Pick<T, K> | 部分選択 | 特定のプロパティのみ抽出 |
Omit<T, K> | プロパティ除外 | 特定のプロパティを除去 |
Record<K, V> | マップ構造 | キーと値のペアによるオブジェクト型定義 |
typescript
interface Product { id: number; name: string; price: number; description: string }
type UpdateProductRequest = Partial<Omit<Product, 'id'>>
type ProductSummary = Pick<Product, 'id' | 'name' | 'price'>
type CategoryCount = Record<string, number>- 同一型から派生するバリエーションはユーティリティ型で生成します。プロパティを手動でコピーしません。
11.3.2. API レスポンス型の定義パターン
API レスポンスはジェネリックラッパー型で一貫した構造を維持します。
typescript
// src/types/common.ts
interface ApiResponse<T> {
success: boolean
data: T
message: string
}
interface PaginatedResponse<T> {
items: T[]
page: number
pageSize: number
totalItems: number
totalPages: number
}
interface ApiError {
code: string
message: string
details?: Record<string, string[]>
}
// 活用例
async function fetchOrders(page: number): Promise<ApiResponse<PaginatedResponse<OrderDto>>> {
const response = await api.get('/orders', { params: { page } })
return response.data
}- すべての API レスポンス関数に戻り値の型を明示します。型推論に依存しません。
11.3.3. ジェネリックコンポーネント
共通コンポーネントはジェネリックを活用して型安全性を維持します。
vue
<script setup lang="ts" generic="T extends { id: number; label: string }">
defineProps<{ options: T[]; modelValue: T | null }>()
const emit = defineEmits<{ 'update:modelValue': [value: T] }>()
</script>ジェネリック Composable は、さまざまな型に対して同一のロジックを再利用します。
typescript
// src/composables/useAsyncData.ts
import { ref, type Ref } from 'vue'
export function useAsyncData<T>(fetcher: () => Promise<T>) {
const data = ref<T | null>(null) as Ref<T | null>
const loading = ref(false)
async function execute() {
loading.value = true
try { data.value = await fetcher() }
finally { loading.value = false }
}
return { data, loading, execute }
}11.3.4. Readonly と不変性
変更してはならないデータには不変型を適用します。
typescript
// Readonly — オブジェクトプロパティの変更防止
const config: Readonly<{ apiBaseUrl: string; maxRetries: number }> = {
apiBaseUrl: 'https://api.example.com',
maxRetries: 3,
}
// ReadonlyArray — 配列の変更防止
function calculateTotal(items: ReadonlyArray<{ price: number; qty: number }>): number {
return items.reduce((sum, item) => sum + item.price * item.qty, 0)
}
// as const — リテラル型の固定
const HTTP_STATUS = { OK: 200, NOT_FOUND: 404, SERVER_ERROR: 500 } as const
type HttpStatusCode = (typeof HTTP_STATUS)[keyof typeof HTTP_STATUS] // 200 | 404 | 500- 設定オブジェクト、定数テーブルには
as constを適用してリテラル型を保持します。 - 関数パラメータとして配列を受け取る際、内部で変更しない場合は
ReadonlyArray<T>を使用します。