ECサイトの商品フィルタリングやダッシュボードのデータ集計など、動的なグルーピング処理を実装する場面がありますが、実行時まで分からないキーを持つオブジェクトは型安全性を確保するのが困難です。
// このように2段階ネストしたグルーピングを型安全に実装したい
{ "Electronics": { "High-end": [product1], "Budget": [product2] } }
今回はそれを叶えるためにRecord型とreduceを組み合わせた動的グルーピングの実装方法を紹介します。
Record型による型安全な動的構造
// Record型による動的グルーピング
type GroupedData = Record<string, Product[]>
interface Product {
id: string
productProperties: Array<{
property: { name: string }
propertyOptions: Array<{ option: { value: string } }>
}>
}
reduceによる動的グルーピング
const groupProductsByProperty = (
products: Product[],
propertyName: string,
): GroupedData => {
return products.reduce<GroupedData>((acc, product) => {
// 商品から指定されたプロパティを検索
const property = product.productProperties.find(
(prop) => prop.property.name === propertyName,
)
if (!property || property.propertyOptions.length === 0) {
// プロパティが見つからない場合は「その他」に分類
if (!acc['その他']) acc['その他'] = []
acc['その他'].push(product)
} else {
// 各プロパティオプションに対して商品を追加
property.propertyOptions.forEach((option) => {
const { value } = option.option
if (!acc[value]) acc[value] = []
acc[value].push(product)
})
}
return acc
}, {})
}
使用例
// 基本的な使用方法
const groupedData = groupProductsByProperty(products, 'category')
// Record型による型安全なアクセス
Object.entries(groupedData).forEach(([category, items]) => {
console.log(`${category}: ${items.length}件`)
})
// 特定カテゴリの商品を安全に取得
const electronicsProducts = groupedData['Electronics'] || []
まとめ
| 技術 | 効果 |
|---|---|
| Record型 | 動的キーでも型安全性を保持 |
| reduce + find | 関数型で配列からオブジェクトへの変換 |