TypeScriptでReactのPropsとStateに型を定義する方法!初心者向け完全ガイド
生徒
「Reactでアプリを作っているのですが、TypeScriptを使うとデータの型を決めないといけないと聞きました。PropsやStateに型をつけるのは難しいですか?」
先生
「全然難しくありませんよ。TypeScriptを使うことで、どのデータがどこに流れているのかが明確になり、ミスを劇的に減らすことができます。特にPropsとStateはReactの基本なので、ここをマスターすれば開発がぐっと楽になります。」
生徒
「具体的にはどのように型を書いていけばいいのでしょうか?」
先生
「まずは型を定義するための基本的な書き方から、一歩ずつ順番に見ていきましょう!」
1. TypeScriptとReactの型定義とは?
TypeScriptは、JavaScriptというプログラミング言語に「型(かた)」というルールを追加したものです。Reactで開発をする際、データのやり取りに型を定義することで、プログラミングのミスを事前に防ぐことができます。パソコンを触ったことがない方でもイメージしやすいように例えると、型とは「お弁当箱の仕切り」のようなものです。ご飯を入れる場所にはご飯を、おかずを入れる場所にはおかずを入れるように、数字を入れる場所には数字を、文字を入れる場所には文字を入れるという約束事を決めるのが型定義です。
ReactにおけるProps(プロップス)は、親の部品から子の部品へ渡される「引継ぎデータ」です。一方でState(ステート)は、その部品の中で変化する「状態」を管理するためのデータです。これらに型をつけることで、間違った種類のデータを渡してしまったときに、コンピュータがすぐに「それは間違いですよ」と教えてくれるようになります。これが検索エンジン最適化(SEO)でも注目される、品質の高いコードを書くための第一歩となります。
2. Props(プロップス)に型を定義する基本
Propsに型を定義する際は、まず「どのようなデータを受け取るか」という設計図を作ります。この設計図のことをTypeScriptでは「インターフェース(interface)」や「型エイリアス(type)」と呼びます。例えば、ユーザーの名前を表示するコンポーネントを作る場合、名前が「文字列(string)」であることを指定します。これにより、間違って数字を渡してしまうようなミスを防ぐことができます。
具体的な書き方を見てみましょう。ここでは、挨拶を表示するシンプルなコンポーネントを作成します。nameという文字データと、ageという数字データを受け取る例です。
type WelcomeProps = {
name: string;
age: number;
};
const Welcome = (props: WelcomeProps) => {
return (
<div>
<h1>こんにちは、{props.name}さん!</h1>
<p>あなたは{props.age}歳ですね。</p>
</div>
);
};
このコードでは、WelcomePropsという名前で型を定義しました。stringは「文字列」、numberは「数値」を意味します。初心者の皆さんは、まずこの二つの型を覚えるだけで、多くの場面で役立ちます。
3. State(ステート)の型定義とuseStateの使い方
次に、部品の中でデータが変化する「State」に型をつける方法を学びます。ReactではuseStateという機能を使って状態を管理しますが、TypeScriptではこのuseStateに型を指定することができます。型を指定しない場合でも、TypeScriptが最初に入れた値から型を予想してくれる「型推論」という便利な機能がありますが、複雑なデータを扱う場合は自分できちんと型を指定するのが一般的です。
例えば、ボタンを押すと数字が増えるカウンターを作ってみましょう。この時、カウンターの数字は必ず「数値(number)」であるべきです。
import React, { useState } from 'react';
const Counter = () => {
// <number>と書くことで、countが数値であることを指定します
const [count, setCount] = useState<number>(0);
const increment = () => {
setCount(count + 1);
};
return (
<div>
<p>現在の値: {count}</p>
<button onClick={increment}>増やす</button>
</div>
);
};
useState<number>(0)という書き方に注目してください。この< >の中に型を書くのがルールです。もし、ここでsetCount("文字列")のように、数字以外のものを入れようとすると、TypeScriptがエラーを出して止めてくれます。これにより、プログラムが変な動きをするのを未然に防げるのです。
4. 複数のデータを持つオブジェクトの型定義
実際の開発では、名前や年齢、住所など、複数のデータが一つにまとまった「オブジェクト」という形式をよく使います。これに型をつけるのは少し難しく感じるかもしれませんが、これまでの応用に過ぎません。例えば、会員登録の情報を扱う場合、一つの変数に複数の情報が入ります。
オブジェクトの型を定義することで、そのデータの中にどんな項目が含まれているのかが、書いている最中にひと目で分かるようになります。これは、大規模なウェブサイト制作やフロントエンド開発において非常に重要な技術です。
type UserInfo = {
id: number;
username: string;
isLoggedIn: boolean;
};
const UserStatus = () => {
const [user, setUser] = useState<UserInfo | null>(null);
const login = () => {
setUser({
id: 1,
username: "プログラミング初心者",
isLoggedIn: true
});
};
return (
<div>
{user ? (
<p>ログイン中: {user.username}</p>
) : (
<button onClick={login}>ログインする</button>
)}
</div>
);
};
ここで出てきたboolean(ブーリアン)は、「はい(true)」か「いいえ(false)」のどちらか一方だけを持つ型です。また、| nullという書き方は、最初はデータが「空っぽ(null)」の状態もあり得ることを示しています。このように柔軟に型を組み合わせることができるのも、TypeScriptの大きなメリットです。
5. コンポーネントに型を適用する実戦的な方法
Reactのコンポーネント自体にも型をつける方法があります。最近のReact開発では、関数の形をしたコンポーネント(関数コンポーネント)が主流です。これに対してReact.FC(FCはFunctional Componentの略)という型を使うことがあります。これを使うと、自動的にchildren(その部品の中にさらに部品を入れる機能)などの型が含まれるようになりますが、初心者のうちは先ほど紹介した引数に直接型を書く方法でも全く問題ありません。
まずは自分が読みやすいと感じる書き方で、しっかりと型を意識して書く練習をしましょう。型を定義することは、未来の自分へのメッセージでもあります。数ヶ月後にそのコードを見返したとき、型が書いてあれば「この部品は何のデータが必要だったのか」がすぐに思い出せます。これはSEOに強いブログ記事を書くために構成案を作る作業と似ており、事前の準備が後の効率を大きく変えるのです。
6. 配列データの型定義と注意点
最後に、データの集まりである「配列」に型をつける方法を解説します。例えば、TODOリストを作る場合、文字の集まり(配列)を扱います。このとき、型はstring[]のように書きます。これは「文字列のリストですよ」という意味になります。配列に型をつけておかないと、リストの中に予期せぬ種類のデータが混じってしまい、表示の際にバグが発生する原因になります。
import React, { useState } from 'react';
const TodoList = () => {
// 文字列の配列型を指定します
const [todos, setTodos] = useState<string[]>([]);
const addTodo = () => {
setTodos([...todos, "新しいタスク"]);
};
return (
<div>
<button onClick={addTodo}>タスクを追加</button>
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>
</div>
);
};
実行結果を確認すると、ボタンを押すごとに「新しいタスク」という文字が画面に増えていきます。もし、ここで数字を追加しようとすると、プログラムが実行される前に警告が出て、間違いに気づくことができます。パソコン操作に慣れていない方にとって、どこで間違えたかをすぐ教えてくれるTypeScriptは、非常に心強い味方になってくれるはずです。