カテゴリ: React 更新日: 2026/01/08

React(TypeScript)で学ぶStateの型推論と型指定の違い!型安全なState管理を初心者向けにやさしく解説

Stateの型推論と型指定の違い
Stateの型推論と型指定の違い

先生と生徒の会話形式で理解しよう

生徒

「Reactでボタンを押した回数みたいな“状態”を持てるって聞きました。TypeScriptだと型ってどうなるんですか?」

先生

「ReactのStateは、TypeScriptだと“型推論”で自動的に型が決まることが多いです。ただし、場面によっては自分で“型指定”した方が安全になります。」

生徒

「型推論と型指定って、何が違うんですか?どっちを使えばいいのか迷います…」

先生

「違いは“最初の値だけで決めて良いか”と“これから入る値の種類を先に決めたいか”です。たとえば、最初は空っぽだけど後でデータが入るStateは、型指定がとても役に立ちます。」

生徒

「なるほど…!まずは、基本から順番に教えてください!」

1. ReactのStateとは?TypeScriptと一緒に考える

1. ReactのStateとは?TypeScriptと一緒に考える
1. ReactのStateとは?TypeScriptと一緒に考える

ReactのState(ステート)は、画面の中で変化する情報を入れておく箱です。たとえば「入力欄の文字」「チェックのオンオフ」「読み込み中かどうか」「ボタンを押した回数」など、ユーザーの操作や通信結果で変わるものをStateで管理します。

TypeScriptは型(かた)を使って「この箱には数字だけ」「この箱には文字だけ」のようにルールを決められます。型があると、間違った値を入れようとした瞬間に気づけるので、バグ(不具合)を減らせます。ReactとTypeScriptを組み合わせると、型安全(かたあんぜん)なState管理がしやすくなります。

用語メモ:「型推論」は、TypeScriptがコードを見て自動で型を考えてくれる仕組みです。「型指定」は、開発者が先に型をはっきり書いて決めることです。

2. Stateの型推論とは?useStateが“最初の値”から型を決める

2. Stateの型推論とは?useStateが“最初の値”から型を決める
2. Stateの型推論とは?useStateが“最初の値”から型を決める

ReactではStateを作るときにuseStateをよく使います。TypeScriptでは、useStateに入れる最初の値を見て、Stateの型を自動で決めることが多いです。これがStateの型推論です。


import React, { useState } from "react";

export default function App() {
  // 最初の値が 0 なので、count は number(数字)だと推論される
  const [count, setCount] = useState(0);

  return (
    

回数:{count}

); }
(画面に「回数:0」が表示され、ボタンを押すたびに数字が1ずつ増えて表示されます)

この例では、最初の値が数字の0なので、TypeScriptは「countは数字だ」と判断します。その結果、setCount("こんにちは")のように文字を入れようとすると、エラーとして教えてくれます。初心者にとっては、間違いが早めに見つかるのが大きな安心ポイントです。

3. Stateの型指定とは?“あとで入る値”まで見越して先に決める

3. Stateの型指定とは?“あとで入る値”まで見越して先に決める
3. Stateの型指定とは?“あとで入る値”まで見越して先に決める

一方で、最初の値だけでは型がうまく決まらないことがあります。たとえば「最初は何もない(null)けど、あとでユーザー情報が入る」Stateです。最初がnullだと、TypeScriptは「nullしか入らない箱」と勘違いしやすくなります。

よくあるつまずき:最初に null や空配列 [] を入れたせいで、あとから正しいデータを入れようとしても型エラーになることがあります。

import React, { useState } from "react";

type User = {
  id: number;
  name: string;
};

export default function App() {
  // User か null が入る、と先に型指定する(ジェネリクス)
  const [user, setUser] = useState<User | null>(null);

  return (
    
{user ?

こんにちは、{user.name}さん

:

ユーザー未設定

}
); }
(最初は「ユーザー未設定」と表示され、ボタンを押すと「こんにちは、さくらさん」に変わります)

ここで出てきたジェネリクスは、「型の入れ物に、あとから型を差し込む書き方」です。useState<User | null>のように書くと、「userにはUserかnullが入る」と宣言できます。こうしておくと、最初がnullでも、あとでUserを入れられます。

また、union型(ユニオンがた)は「AかBのどちらか」という意味です。ここでは「Userかnull」のどちらか、というルールになります。現実の例えだと、「席には人が座っているか、空席(null)か」のようなイメージです。

4. 型推論と型指定の“違い”を一言でいうと?

4. 型推論と型指定の“違い”を一言でいうと?
4. 型推論と型指定の“違い”を一言でいうと?
  • 型推論:最初の値を見て、TypeScriptが「このStateはたぶんこれ!」と自動で決める
  • 型指定:最初の値だけに頼らず、「このStateには将来これが入る」と先にルールを決める

型推論は書く量が少なくて楽です。ですが、アプリが少し大きくなると「最初は空」「あとで入る」「複数の形がある」といったStateが増えます。そんなとき、型指定を使うと未来の自分やチームを助ける説明書になります。

5. 初心者が迷いやすいパターン:空配列・空オブジェクトのState

5. 初心者が迷いやすいパターン:空配列・空オブジェクトのState
5. 初心者が迷いやすいパターン:空配列・空オブジェクトのState

特に初心者が混乱しやすいのが、配列(リスト)やオブジェクト(まとまり)のStateです。たとえば、最初はデータがないので空配列で始めたいことがあります。ここで型推論だけに頼ると、意図しない型になってしまうことがあります。


import React, { useState } from "react";

type Todo = {
  id: number;
  title: string;
  done: boolean;
};

export default function App() {
  // 配列に Todo が入る、と型指定しておくと安全
  const [todos, setTodos] = useState<Todo[]>([]);

  return (
    

件数:{todos.length}

); }
(最初は「件数:0」で、ボタンを押すと件数が増えていきます)

このようにuseState<Todo[]>([])と書くと、「この配列にはTodoだけが入る」と決められます。ReactのState管理で配列を扱うときは、あとから追加・削除・更新がよく起きるので、型指定があると安心です。

6. “nullチェック”と型安全:安全に読み出す考え方

6. “nullチェック”と型安全:安全に読み出す考え方
6. “nullチェック”と型安全:安全に読み出す考え方

型指定でUser | nullのようにすると、読み出すときに「nullかもしれない」ことを忘れにくくなります。これがTypeScriptの大事なところです。もしnullのままuser.nameに触ろうとすると、画面が止まる原因になることがあります。

そこでReactでは、条件分岐(条件によって表示を変える)と組み合わせて安全に表示します。上の例のuser ? ... : ...は「userがあるならA、ないならB」という意味です。TypeScriptの型指定とReactの条件分岐は相性が良く、初心者でも“事故”を減らせます。

例え:冷蔵庫を開ける前に「牛乳があるか」を確認する感じです。あるならコップに注げますが、ないのに注ごうとすると困ります。nullチェックは、この確認作業に似ています。

7. どんなときに型推論で十分?どんなときに型指定が必要?

7. どんなときに型推論で十分?どんなときに型指定が必要?
7. どんなときに型推論で十分?どんなときに型指定が必要?

目安として、次のように考えると選びやすいです。ReactのuseStateはどちらでも使えますが、アプリの意図をはっきりさせたいときは型指定が強い味方です。

型推論で十分なことが多い例
  • 最初から最後まで同じ種類の値が入る(数字、文字、真偽値など)
  • 初期値がはっきりしていて、あとで形が変わらない
  • 学習用の小さなコンポーネントで、まず動きを理解したい
型指定をおすすめしたい例
  • 最初はnullや空で、あとでデータが入る(API通信、ログイン情報など)
  • 配列やオブジェクトで、中身の形を守りたい
  • 「AかBか」のように複数パターンがあり、union型で表したい

特に「PropsとStateを型安全にしたい」「TypeScriptでReactのバグを減らしたい」と考えるなら、Stateの型指定は避けて通れません。小さなうちは型推論で書きやすく、少し複雑になったら型指定で守りを固める、という順番が自然です。

8. State型の設計で意識したいこと:入力フォームを例にする

8. State型の設計で意識したいこと:入力フォームを例にする
8. State型の設計で意識したいこと:入力フォームを例にする

入力フォームのStateは、初心者がReactのState管理を学ぶときに定番です。たとえば「名前」と「年齢」の入力をまとめて持つ場合、オブジェクトで管理します。ここでも型指定をしておくと、フィールド名の打ち間違いを防げます。


import React, { useState } from "react";

type FormState = {
  name: string;
  age: number;
};

export default function App() {
  const [form, setForm] = useState<FormState>({ name: "", age: 0 });

  return (
    

名前:{form.name}

年齢:{form.age}

); }
(「名前」「年齢」が表示され、ボタンを押すと表示内容が更新されます)

このように型指定しておくと、たとえばageに文字を入れたり、存在しないプロパティ名を書いたりしたときに、TypeScriptが「それは違う」と止めてくれます。ReactのState管理は自由度が高い分、型安全で守ると安心して作業できます。

9. “型推論が強すぎる”ときの対処:リテラル型と広げたい型

9. “型推論が強すぎる”ときの対処:リテラル型と広げたい型
9. “型推論が強すぎる”ときの対処:リテラル型と広げたい型

TypeScriptはとても賢いので、時々「推論が細かすぎる」ことがあります。たとえば、Stateに入れる文字が「loading」「success」「error」のように決まっている場合は、むしろ細かい方が便利です。でも「あとでいろいろな文字が入る」なら、広い型にしたいこともあります。

こうした状態は、ステータス(状態の種類)としてよく出てきます。ここではunion型で安全にしつつ、意図をはっきりさせます。


import React, { useState } from "react";

type Status = "idle" | "loading" | "success" | "error";

export default function App() {
  const [status, setStatus] = useState<Status>("idle");

  return (
    

状態:{status}

); }
(ボタンを押すと「状態:idle」が「loading」「success」「error」に切り替わって表示されます)

このように型指定すると、間違って"loadding"のように打ち間違えてもエラーで気づけます。ReactのStateは画面の見た目や動きに直結するので、ステータス管理は型安全にしておくとトラブルが減ります。

10. setStateの型も一緒に決まる:更新方法が安全になるメリット

10. setStateの型も一緒に決まる:更新方法が安全になるメリット
10. setStateの型も一緒に決まる:更新方法が安全になるメリット

useStateは、State本体だけでなく、更新用の関数であるsetState(例:setCountsetUser)の型も自動で決めます。つまり、型推論や型指定が正しくできていると、更新の仕方まで安全になります。

たとえば数字のStateなら、setCount(count + 1)のように数字の計算が自然に書けますし、文字のStateなら文字の処理が中心になります。逆に、型があいまいだと「今入っているのは数字?文字?」と迷いやすくなり、コードも読みづらくなります。

またReactでは、Stateの更新に関数形式(前の値を受け取って次の値を返す)を使うことがあります。これは「連続でボタンを押したときでも、前の値を正しく元にして更新する」ための書き方です。TypeScriptの型が合っていれば、この関数形式でも引数と戻り値の型がそろい、更新ミスを防げます。

例え:レシートの合計金額を更新するときに、「前の合計に新しい商品代を足す」方が安全です。いきなり合計を決め打ちするより、前の値を元に計算するとズレにくい、という感覚に近いです。
カテゴリの一覧へ
新着記事
New1
React
Reactコンポーネントの再利用と分割を完全マスター!初心者でもわかるコンポーネント設計
New2
React
ReactでAxiosインターセプターの使い方を完全ガイド!初心者でもわかるリクエストとレスポンスの処理方法
New3
React
JSXの書き方!初心者でもわかるReactタグと属性の基本ルール解説
New4
React
ReactとDockerを使った開発環境構築の基本を徹底解説!初心者でもわかるReactとDockerの連携方法
人気記事
No.1
Java&Spring記事人気No1
React
ReactでonChangeイベントを使ってフォーム入力値を管理する方法を初心者向けに解説
No.2
Java&Spring記事人気No2
React
ReactとTypeScriptの環境構築をやさしく解説!Viteとtsconfigの設定も丁寧に紹介
No.3
Java&Spring記事人気No3
React
Reactのイベントハンドリングのアンチパターンまとめ!初心者でもわかる注意点
No.4
Java&Spring記事人気No4
React
Reactのカスタムフックの作り方を完全ガイド!再利用可能なロジックを切り出す仕組み
No.5
Java&Spring記事人気No5
React
ReactでFetch APIのローディング状態を管理する方法|初心者にもわかる解説
No.6
Java&Spring記事人気No6
React
ReactのuseStateとuseEffectでよくあるエラーと解決方法ガイド!初心者でもわかるReactフック
No.7
Java&Spring記事人気No7
React
create-react-appでReactプロジェクトを作成する手順を初心者向けに完全解説!
No.8
Java&Spring記事人気No8
React
Reactでファイルアップロードを実装する方法を解説!Fetch APIで画像やPDFを送る仕組みを初心者向けに紹介