【実務・中級編】 TypeScriptにおけるオプショナルPropsの定義 – React実践ガイド

なぜ「Propsのオプショナル」で事故が起きるのか?―TypeScriptとReactの危うい関係を制する

現場でコードレビューをしていると、必ずと言っていいほど目にするのが「オプショナルPropsの扱い」にまつわる悲劇です。

「この値はあってもなくてもいいよね」と気軽に `?` を付けた結果、数ヶ月後にコンポーネントが `undefined` の海に飲まれ、レンダリングがクラッシュする……。そんな経験、一度はあるはずです。

今日は、React × TypeScriptにおいて「オプショナルPropsをどう定義し、どう安全にさばくか」という、地味ながらもプロダクトの寿命を左右する極めて重要な話をしよう。

—

1. `?` 修飾子の本質を見抜く

TypeScriptにおける `?` は、単に「値を渡さなくてもいい」という合図ではありません。コンパイラに対して「このプロパティは `undefined` である可能性がある」という契約を突きつけるものです。

多くのエンジニアが陥る罠は、`?` を付けただけで満足し、受け取り側でその `undefined` を放置すること。まずは、一番クリーンな定義の例を見てみよう。

interface ButtonProps {
label: string;
// オプショナルプロパティ。実態は (string | undefined) となる
variant?: ‘primary’ | ‘secondary’;
onClick?: () => void;
}

export const Button = ({ label, variant = ‘primary’, onClick }: ButtonProps) => {
// デフォルト引数で初期値を設定するテクニック
// これにより、コンポーネント内部では variant は必ず ‘primary’ | ‘secondary’ になる
return (

);
};

ここがプロのポイント

  • デフォルト引数の活用: `variant = ‘primary’` のように、関数引数の分割代入でデフォルト値を設定してしまえば、コンポーネント内部で `if (variant === undefined)` といった冗長なガード句を書く必要がなくなります。コードの可読性が段違いです。

—

2. 「`undefined` を許容するか否か」の思想

実務では、`?` を使うべき場面と、あえて使わず `null` や明示的な値を要求すべき場面があります。

もし「値が渡されない場合は、UI自体をレンダリングしたくない」というケースなら、`?` を使わずに `Partial` を使うか、あるいはプロパティ自体を必須(Required)にすることを検討すべきです。

// 逆に「完全に制御したい」場合は、undefined を明示的に許容する型を作るのも手
interface UserProfileProps {
displayName: string | undefined; // ‘?’ を使わず、明示的にundefinedを許可する
}

export const UserProfile = ({ displayName }: UserProfileProps) => {
// 読み取り専用のデータなら、論理積を使って安全に表示する
return

{displayName ?? ‘ゲストユーザー’}

;
};

ブラウザのレンダリングエンジンは、`undefined` が渡されると、それがDOMに直接挿入されない限りは基本的には「無視」を決め込みます。しかし、Reactの仮想DOM上で不要な再レンダリングや、予期せぬ挙動を引き起こすリスクはゼロではありません。`??` (Nullish coalescing operator) を使って、「値がない時のフォールバック」を常にセットで考えるのが現場の流儀です。

—

3. 関数型Propsの「オプショナル」はさらに注意が必要

クリックハンドラのような関数をオプショナルにする場合、もっとも泥臭いのが「呼び出し時の安全確保」です。

interface IconButtonProps {
icon: string;
onAction?: () => void;
}

export const IconButton = ({ icon, onAction }: IconButtonProps) => {
// オプショナルな関数を実行する際、&& を使ったショートサーキット評価が鉄板
// 現場では Optional Chaining (?.) を使うのが今のベストプラクティス
return (

);
};

`onAction?.()` と書くことで、`onAction` が定義されていない場合にエラーにならず、かつ何も実行されないという、極めて安全な挙動を保証できます。古いコードでは `onAction && onAction()` と書かれていることもありますが、今は迷わず Optional Chaining を使いましょう。

—

現場のシニアからのアドバイス

「オプショナルProps」を乱用すると、コンポーネントのAPIがボヤけ、保守が困難になります。以下の指針を意識してみてください。

1. デフォルト値で解決できるなら `?` を使う: コンポーネント内部でハンドリングできるなら、呼び出し元に負担をかけないのが優しさです。
2. 「本当にオプショナルか?」を自問する: 「なんとなくあると便利そう」で付けた `?` は、後から絶対に負債になります。必須にできるなら、必須にしたほうが型定義の堅牢性は高まります。
3. ドキュメントコメントを残す: `/ @default ‘primary’ /` のようにJSDocを書いておけば、エディタ上でホバーした時に他のメンバーが迷わなくなります。

ReactのProps設計は、単なるデータの受け渡しではありません。「このコンポーネントをどう使うのが一番幸せか」を伝えるインターフェース設計そのものです。

次にコードを書くとき、`?` をタイピングする前に、その「問い」を自分に投げかけてみてください。きっと、より美しいコンポーネントが作れるはずです。

コメント

タイトルとURLをコピーしました