React × TypeScript:型定義という名の「信頼」をコードに刻む
やあ。現場でコードを書いていて、「このProps、結局何が渡されるのか実行してみないとわからない」という恐怖に震えたことはないかい?
Reactの柔軟性は諸刃の剣だ。Propsを適当に渡しても動いてしまうからこそ、数ヶ月後の自分やチームメンバーが「このバグ、どこで混入したんだ?」と頭を抱えることになる。
今回は、TypeScriptを使ってコンポーネントに堅牢な「型」を定義し、開発体験(DX)と保守性を極限まで高める方法を伝授する。公式ドキュメントに書いてあるような浅い話は飛ばす。現場で泥臭く戦う君たちに必要な「本質」を話そう。
—
1. なぜ「インターフェース」で定義するのか
まず、ブラウザの視点に立ってみよう。ブラウザはTypeScriptなんて知らない。最終的にJavaScriptにトランスパイルされ、Reactはそれを仮想DOMとして処理する。
重要なのは、「型定義はブラウザのためではなく、未来の君とチームのために存在する」という点だ。
`any`を使えば一瞬でエラーは消えるが、それは「安全装置を外して時速200kmで走る」のと同じだ。Propsのインターフェースを定義することは、コンポーネントに対する「契約書」を作成することに他ならない。
2. 実践的なインターフェース定義のベストプラクティス
現場でよく見る「とりあえず全部オプショナル(`?`)」にする悪癖は今すぐ捨てよう。必要なものは必要、ないものは定義しない。これが鉄則だ。
以下は、実務で頻出するパターンを網羅したコード例だ。
import React from ‘react’;
/
- 現場でよく使うProps定義のテンプレート
- 1. 必須なものはそのまま、任意なものは ? をつける
- 2. 変更不可なデータには readonly をつけることで意図せぬミューテーションを防ぐ
/
interface ButtonProps {
readonly label: string;
readonly onClick: () => void;
// 任意プロパティ:あってもなくても良いもの
readonly variant?: ‘primary’ | ‘secondary’ | ‘danger’;
// 子要素を受け取る場合は React.ReactNode を使うのが定石
readonly children?: React.ReactNode;
}
export const Button: React.FC
label,
onClick,
variant = ‘primary’, // デフォルト値の設定
children
}) => {
return (
);
};
3. ここがプロのポイント:`React.FC`を使うべきか否か
最近のReact界隈で議論になるのが、「`React.FC`を明示的に使うべきか、単なる関数として書くべきか」という点だ。
僕個人の見解としては、「`React.FC`は使わなくていい(または最小限でいい)」派だ。
理由は単純。`React.FC`を使うと、`children`が暗黙的に含まれてしまうからだ。「このコンポーネントは子要素を受け取らないはずなのに、なぜか渡せてしまう」という微妙な型安全性の崩壊を招くことがある。
以下のように、関数の引数に直接型を当てるスタイルの方が、現代的でモダンだ。
// 冗長なReact.FCを廃し、よりピュアに定義するスタイル
interface CardProps {
readonly title: string;
}
export const Card = ({ title }: CardProps) => {
return
;
};
これなら、`children`を渡そうとすればTypeScriptが即座に「そんなプロパティはない」と怒ってくれる。この「厳しい指摘」こそが、デバッグ時間を削減する最大の武器になるんだ。
4. 最後に:型は「ドキュメント」である
コードを書くとき、型定義を「面倒な作業」だと思っていないか?
それは間違いだ。型定義は、コードの読み手に対する最強のドキュメントだ。
IDEのホバー機能で型が表示されるとき、そこに適切な型が定義されていれば、ドキュメントを読みに行かずともそのコンポーネントの使い方がわかる。これがチーム開発における「摩擦」を減らす。
- インターフェースは小さく分割する(巨大なPropsオブジェクトを作らない)
- `type`ではなく`interface`を優先する(宣言的マージが可能で拡張性が高いため)
- 「とりあえずany」は禁句にする(それを打った瞬間に、君のコードの寿命は縮まる)
この3つを意識するだけで、君の書くコードは驚くほど洗練されるはずだ。
Reactは自由だ。その自由を「無法地帯」にするのか、「規律ある表現の場」にするのか。それは、君が今書いているその数行の型定義にかかっている。頑張ってくれ、期待しているよ。

コメント