Reactで理解するuseStateのジェネリック型入門!型安全なState管理を初心者向けにやさしく解説
生徒
「ReactでuseStateを使うときに、<>みたいな記号を見かけたんですが、あれは何ですか?」
先生
「それはジェネリック型といって、Stateの中に入る値の型をはっきり決めるための書き方です。」
生徒
「型は前にも書いたことがありますが、ジェネリックって言われると急に難しく感じます…」
先生
「大丈夫です。考え方はとても単純で、『この箱には何を入れますか?』と先に教えてあげるだけなんですよ。」
1. useStateとジェネリック型の関係とは?
ReactのuseStateは、画面の中で変わる情報を覚えておくための仕組みです。TypeScriptを使うと、そのStateに入る値の型を指定できます。
そのときに使われるのがジェネリック型です。ジェネリック型とは、「あとから中身の型を決められる仕組み」のことです。useStateは、まさにこの仕組みを使って作られています。
難しく聞こえますが、実際には「このStateには文字を入れる」「このStateには数の情報を入れる」と、先にルールを決めているだけです。これにより、ReactとTypeScriptを組み合わせた型安全なState管理が実現できます。
2. ジェネリック型を使わないuseStateの問題点
useStateは、型を書かなくても使えます。最初の値を見て、TypeScriptが自動で型を判断してくれるからです。ただし、この方法には落とし穴があります。
たとえば、最初は何も入っていないStateや、あとからデータが変わるStateの場合、TypeScriptが正しく判断できないことがあります。その結果、「本当は入れていい値なのにエラーになる」「逆に、入れてはいけない値が通ってしまう」といった問題が起こります。
そこで役立つのが、useStateのジェネリック型です。ジェネリック型を使うことで、「今は空だけど、将来はこの型が入る」とはっきり伝えられます。
3. useStateでジェネリック型を書く基本の形
useStateでジェネリック型を使うときの基本の形は、とてもシンプルです。useStateの後ろに、<型>を書くだけです。
import React, { useState } from "react";
function App() {
const [message, setMessage] = useState<string>("こんにちは");
return (
<div>
<h1>{message}</h1>
</div>
);
}
export default App;
この<string>の部分がジェネリック型です。「このStateには文字列が入りますよ」とTypeScriptに伝えています。これにより、setMessageで数字などを入れようとすると、すぐにエラーで気づけます。
4. なぜジェネリック型が必要なのか?初心者向けの例え
ジェネリック型は、箱に貼るラベルのようなものです。ラベルがない箱には、何でも入れてしまいがちですが、ラベルがあれば迷いません。
「この箱は果物専用」「この箱は書類専用」と書いてあれば、間違って別のものを入れずに済みます。useStateのジェネリック型も同じで、「このStateはこの型専用」というラベルを貼る役割をしています。
Reactの画面はStateの中身によって動くため、このラベルがあることで、予期しない画面の崩れやエラーを防げます。
5. nullと一緒に使うジェネリック型
実際のReact開発では、「最初は何もないが、あとでデータが入る」Stateがよくあります。たとえば、ログインユーザーの情報などです。
このような場合、ジェネリック型とunion型を組み合わせます。union型とは、「AかBのどちらか」という意味の型です。
type User = {
name: string;
age: number;
};
function App() {
const [user, setUser] = useState<User | null>(null);
return (
<div>
{user ? <p>{user.name}</p> : <p>ユーザー未設定</p>}
</div>
);
}
このように書くことで、「userにはUserかnullが入る」と明確になります。ジェネリック型がないと、この意図を正しく伝えるのが難しくなります。
6. 配列Stateとジェネリック型の組み合わせ
配列をStateで扱う場合も、ジェネリック型はとても重要です。特に、最初が空配列の場合は、型指定をしないと中身が不明な配列になってしまいます。
type Todo = {
id: number;
title: string;
};
function App() {
const [todos, setTodos] = useState<Todo[]>([]);
return (
<div>
<p>件数:{todos.length}</p>
</div>
);
}
useState<Todo[]>と書くことで、「この配列にはTodo型のデータだけが入る」と決まります。これにより、配列操作でも型安全が保たれます。
7. ジェネリック型はPropsとState管理の基礎
ジェネリック型は、useStateだけでなく、Propsや関数など、TypeScriptのさまざまな場面で使われています。Reactにおいては、特にState管理での利用頻度が高いです。
最初は<T>や<string>といった記号に戸惑うかもしれませんが、「中身の型を指定しているだけ」と考えると理解しやすくなります。
useStateでジェネリック型を正しく使えるようになると、ReactとTypeScriptのコードが一気に読みやすくなり、安心して開発できるようになります。
8. 初心者が意識したいジェネリック型の考え方
ジェネリック型を使うときは、「このStateには何が入るのか」を言葉で説明できるかを意識すると良いです。その説明を、そのまま型として書くイメージです。
ReactのuseStateは自由度が高い分、型指定をしないとミスが起こりやすくなります。ジェネリック型は、その自由さに安全ベルトを付けるような存在です。
まずは文字列・数値・オブジェクト・配列といった基本的な型で、ジェネリック型を使う練習をすると、自然と理解が深まります。