こんにちは!Reactの世界へようこそ。チーフアーキテクトの私です。
Reactを触り始めて、「あ、このコンポーネント、さっき作ったやつとほとんど同じなのに、一部のボタンだけ無くしたいな……」なんて壁にぶつかったことはありませんか?
「また一から同じような型を書かなきゃいけないの?」とため息をついたそこのあなた、大丈夫ですよ。今日はその面倒な作業を劇的に楽にしてくれる、TypeScriptの魔法の道具`Pick`と`Omit`についてお話ししますね。
これらを使いこなせるようになると、コードのコピペ地獄から抜け出し、まるでオーダーメイドの洋服を仕立てるかのようにスマートに型を組めるようになりますよ。
—
1. なぜPropsのフィルタリングが必要なの?(お買い物の例え)
突然ですが、街の洋服屋さんを想像してみてください。
そこには、とても便利な「万能ジャケット」が売っています。このジャケットには、以下の機能(Props)が全部ついているとしましょう。
- 色 (`color`)
- サイズ (`size`)
- 価格 (`price`)
- フードの有無 (`hasHood`)
さて、ここであなたのお店で「子ども用のフードなしパーカー」を新しく売り出すことになりました。
このとき、大人の万能ジャケットの設計図(型)をそのまま使ったらどうなるでしょう? 「フードの有無」なんて本当はいらないのに、無理やりつけなきゃいけなくなったり、余計なバグの温床になったりしますよね。
かといって、子ども用パーカーのためにゼロから設計図を書き直すのも、なんだかコードがもったいない(DRY原則に反する)気がしませんか?
そんなときに使うのが、既存の設計図から「ここだけ欲しい!」と摘み食いしたり、「ここは要らない!」と切り捨てたりできる`Pick`と`Omit`なんです。
—
2. 「Pick(ピック)」:欲しいものだけをスマートに摘み取る
まずは`Pick`から見ていきましょう。`Pick`は、英語の「摘み取る(ピックアップする)」のイメージそのままです。
既存の大きな型から、「このプロパティとこのプロパティだけが欲しい!」というときに使います。
コードで見てみよう
例えば、先ほどの万能ジャケットの型(Props)がこうあったとします。
// 元となる万能ジャケットの型
type JacketProps = {
color: string;
size: string;
price: number;
hasHood: boolean;
};
ここから、「色」と「サイズ」だけを厳選して使いたい!という新しいコンポーネントを作るとき、`Pick`はこう書きます。
// JacketProps から color と size だけを「摘み取る」
type SimpleJacketProps = Pick
// 出来上がった SimpleJacketProps の中身は、実質こうなっています:
// {
// color: string;
// size: string;
// }
すごくスッキリしましたよね!「あれもこれも」と書く必要がなく、元の型が変わったときも自動で追従してくれるので、メンテナンス性も抜群に上がります。
—
3. 「Omit(オミット)」:いらないものをスパッと除外する
続いては`Omit`です。`Omit`は、「省く」「除外する」という意味を持っています。
こちらは、既存の型から「このプロパティ以外は全部使いたい!」という、引き算の考え方をする時に大活躍します。
コードで見てみよう
先ほどの万能ジャケットから、「価格(price)」だけを隠した(一般公開しない)スタッフ専用の表示用コンポーネントを作りたいとします。
そんなときは`Omit`の出番です。
// JacketProps から price だけを「除外する(取り除く)」
type StaffJacketProps = Omit
// 出来上がった StaffJacketProps の中身は、実質こうなっています:
// {
// color: string;
// size: string;
// hasHood: boolean;
// }
「あれもこれも全部入れるけど、これだけは絶対に入れたくない!」という引き算の美学が、この`Omit`には詰まっています。既存のUIライブラリ(MUIやChakra UIなど)のボタンの型を拡張するときにも、この`Omit`は毎日のように実務で使いますよ。
—
4. 【実践】Reactコンポーネントでの具体的な使い方
では、実際にReactのコンポーネントの中でどうやってこれらが動くのか、コピペしてすぐに動かせるサンプルコードで確認してみましょう。
今回は、ボタンコンポーネントをベースにして、それを少し特殊なカード用のボタンにアレンジする例を考えてみます。
import React from ‘react’;
// 1. 基本となるボタンの型を定義します
type BaseButtonProps = {
label: string; // ボタンの文字(必須)
onClick: () => void; // クリックされた時の処理(必須)
backgroundColor: string; // 背景色(必須)
disabled: boolean; // 無効化フラグ(必須)
};
// 2. 「BaseButton」をそのまま定義
const BaseButton: React.FC
return (
);
};
// ==========================================
// ここからが Pick と Omit の本番です!
// ==========================================
// 3. 【Pickの例】
// カード用の特別なボタンを作ります。
//ここでは「label」と「onClick」の2つだけをBaseButtonから拝借(Pick)します。
// (背景色やdisabledはカード側で固定しちゃうので不要!)
type CardButtonProps = Pick
const CardButton: React.FC
return (
);
};
// 4. 【Omitの例】
// 管理画面用のボタンを作ります。
// これはBaseButtonの機能ほぼ全て欲しいけれど、「backgroundColor(背景色はシステム側で強制的に決まるため)」だけを除外(Omit)したい!
type AdminButtonProps = Omit
const AdminButton: React.FC
return (
);
};
このように、ベースとなるコンポーネントの型を軸にして、「足し算・引き算」感覚でスマートに派生型を作れるのが、`Pick`と`Omit`の最高に気持ちいいところです。
—
チーフアーキテクトからのアドバイス
実務でコードを書いていると、ついつい「めんどくさいから、新しい型を全部イチから書いちゃおう!」となりがちです。
ですが、それをやってしまうと、元のコンポーネントの仕様が変わったときに、あっちこッチの型を直す羽になり、バグの温床になってしまいます。「DRY(Don’t Repeat Yourself:同じことを何度も書かない)」の原則は、ロジックだけでなくTypeScriptの「型」の世界でも同じくらい大切です。
「あ、このProps、さっきのあいつとほとんど一緒だな」と思ったら、ぜひ一度立ち止まって、`Pick`や`Omit`でスマートに再利用できないか考えてみてください。あなたの書くReactコードが、ぐっと洗練されたプロの仕上がりになりますよ。
それでは、また次の現場でお会いしましょう!Happy Hacking!

コメント