カテゴリ: React 更新日: 2026/02/14

TypeScriptでイベントハンドラを型定義する方法を完全解説!初心者でもわかるReactの基本

TypeScriptでイベントハンドラを型定義する方法
TypeScriptでイベントハンドラを型定義する方法

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

生徒

「Reactでボタンをクリックしたり入力フォームを使ったりするときにイベントハンドラを書きますよね?TypeScriptだと型も書かないといけないんですか?」

先生

「そうですね。TypeScriptを使うとイベントハンドラにも型を付けることができます。型を付けると間違った書き方を防げるので安心です。」

生徒

「イベントハンドラの型ってどうやって書くんですか?難しそうです…」

先生

「大丈夫ですよ。いくつかの基本的な型を覚えておけば簡単に使えるので、一緒に見ていきましょう!」

1. イベントハンドラとは?

1. イベントハンドラとは?
1. イベントハンドラとは?

イベントハンドラとは、ボタンをクリックしたり、入力フォームに文字を入力したときに呼び出される関数のことです。例えば、「ボタンを押したらメッセージを変える」という動きはイベントハンドラで実現します。

JavaScriptだけでも書けますが、TypeScriptを使うと「どんなイベントを受け取る関数なのか」を型で指定できるため、安心してプログラムを書けます。

2. クリックイベントの型定義

2. クリックイベントの型定義
2. クリックイベントの型定義

最もよく使うのはボタンのクリックイベントです。ReactとTypeScriptではReact.MouseEventHandler<HTMLButtonElement>を使います。


import React, { useState } from "react";

const ClickButton: React.FC = () => {
  const [message, setMessage] = useState("こんにちは!");

  const handleClick: React.MouseEventHandler<HTMLButtonElement> = (event) => {
    setMessage("ボタンがクリックされました!");
  };

  return (
    <div>
      <h1>{message}</h1>
      <button onClick={handleClick}>クリックしてみよう</button>
    </div>
  );
};

export default ClickButton;
(画面に「こんにちは!」と表示され、ボタンを押すと「ボタンがクリックされました!」に変わります)

ここで使っているReact.MouseEventHandler<HTMLButtonElement>は「マウスイベントを扱うボタン専用の関数です」という意味です。

3. 入力フォームのイベント型

3. 入力フォームのイベント型
3. 入力フォームのイベント型

次に、入力フォーム(input要素)の値を受け取るイベントハンドラです。こちらはReact.ChangeEventHandler<HTMLInputElement>を使います。


const InputForm: React.FC = () => {
  const [text, setText] = useState("");

  const handleChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
    setText(event.target.value);
  };

  return (
    <div>
      <input type="text" value={text} onChange={handleChange} />
      <p>入力内容: {text}</p>
    </div>
  );
};
(画面にテキストボックスが表示され、入力すると下に入力内容がリアルタイムで表示されます)

event.target.valueは「入力された文字」を意味します。型を指定しているので、数値を入れようとしてもエラーになります。

4. フォーム送信イベントの型

4. フォーム送信イベントの型
4. フォーム送信イベントの型

フォーム全体を送信する場合は、React.FormEventHandler<HTMLFormElement>を使います。


const SubmitForm: React.FC = () => {
  const [text, setText] = useState("");

  const handleSubmit: React.FormEventHandler<HTMLFormElement> = (event) => {
    event.preventDefault(); // ページのリロードを防ぐ
    alert("送信された内容: " + text);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" value={text} onChange={(e) => setText(e.target.value)} />
      <button type="submit">送信</button>
    </form>
  );
};
(画面に入力フォームと送信ボタンが表示され、送信するとアラートに入力内容が表示されます)

event.preventDefault()は、ブラウザの標準動作(リロード)を止めるために使います。

5. よく使うイベントハンドラ型一覧

5. よく使うイベントハンドラ型一覧
5. よく使うイベントハンドラ型一覧

初心者の方がよく使うイベントの型をまとめると次のようになります。

  • クリックイベント → React.MouseEventHandler<HTMLButtonElement>
  • 入力フォームの変更 → React.ChangeEventHandler<HTMLInputElement>
  • フォーム送信 → React.FormEventHandler<HTMLFormElement>
  • チェックボックスの変更 → React.ChangeEventHandler<HTMLInputElement>
  • セレクトボックスの選択 → React.ChangeEventHandler<HTMLSelectElement>

このように、使う要素に応じて型を指定するだけで、エディタが入力補完してくれるのでミスが減ります。

6. 型定義を使うメリット

6. 型定義を使うメリット
6. 型定義を使うメリット

TypeScriptでイベントハンドラを型定義すると次のメリットがあります。

  • 入力補完が効いて使えるプロパティがすぐに分かる
  • 間違った要素に対してイベントを使おうとするとエラーで気づける
  • 複雑なフォームでも安心して管理できる

最初は少し長く感じるかもしれませんが、慣れるととても便利で安全な方法になります。

まとめ

まとめ
まとめ

今回の記事では、ReactとTypeScriptを組み合わせて開発を行う際に避けては通れない、イベントハンドラの型定義について詳しく解説してきました。フロントエンド開発において、ユーザーの操作(クリックや入力、送信など)を正確に制御することは、アプリケーションの品質を左右する非常に重要な要素です。

TypeScriptでイベントを扱う重要性

JavaScriptでの開発に慣れていると、最初は「なぜわざわざ型を指定しなければならないのか」と手間に感じることもあるかもしれません。しかし、TypeScriptを導入する最大の恩恵は、「実行前にエラーに気づけること」「開発効率が圧倒的に向上すること」にあります。

例えば、event.target.valueを参照しようとした際、そのイベントが本当に値を保持している要素(inputやtextareaなど)から発生したものかどうかを、コードを動かす前にエディタが教えてくれます。これにより、本番環境で「undefinedで動かない」といった初歩的なバグを劇的に減らすことができるのです。

実践的な応用例:複数のイベントを組み合わせる

これまでの学習を踏まえて、もう少し実践的な「ログインフォーム」のようなコンポーネントを考えてみましょう。ここでは、複数の入力項目の型定義と、送信時の処理を一つのコンポーネントにまとめています。


import React, { useState } from "react";

/**
 * ユーザー情報の型定義
 */
type UserFormState = {
  email: string;
  role: "admin" | "user";
};

const AdvancedForm: React.FC = () => {
  const [formData, setFormData] = useState<UserFormState>({
    email: "",
    role: "user",
  });

  // テキスト入力とセレクトボックスの変更をハンドル
  const handleInputChange: React.ChangeEventHandler<HTMLInputElement | HTMLSelectElement> = (event) => {
    const { name, value } = event.target;
    setFormData((prev) => ({
      ...prev,
      [name]: value,
    }));
  };

  // フォーム送信のハンドル
  const handleSubmit: React.FormEventHandler<HTMLFormElement> = (event) => {
    event.preventDefault();
    console.log("送信データ:", formData);
    alert(`送信完了: ${formData.email} (${formData.role})`);
  };

  return (
    <div className="container mt-4">
      <form onSubmit={handleSubmit} className="border p-4 shadow-sm">
        <div className="mb-3">
          <label className="form-label">メールアドレス</label>
          <input
            type="email"
            name="email"
            className="form-control"
            value={formData.email}
            onChange={handleInputChange}
            required
          />
        </div>
        <div className="mb-3">
          <label className="form-label">権限</label>
          <select
            name="role"
            className="form-select"
            value={formData.role}
            onChange={handleInputChange}
          >
            <option value="user">一般ユーザー</option>
            <option value="admin">管理者</option>
          </select>
        </div>
        <button type="submit" className="btn btn-primary">
          登録する
        </button>
      </form>
    </div>
  );
};

export default AdvancedForm;
(画面にメールアドレス入力欄と権限選択のプルダウンが表示されます。入力して登録ボタンを押すと、入力内容がアラートで表示され、コンソールにデータが出力されます)

型定義をマスターするための3つのポイント

  1. ジェネリクス(< >)を意識する: React.ChangeEventHandler<HTMLInputElement> のように、山括弧の中に対象となるHTML要素を記述するのがReactの基本ルールです。
  2. React.FC(Function Component)を活用する: コンポーネント自体に型を付けることで、propsの型定義もスムーズに行えるようになります。
  3. エディタの補完を信じる: 自分で全ての型を暗記する必要はありません。React.まで入力して、出てくる候補から適切なイベント(Click, Change, Formなど)を探す癖をつけましょう。

TypeScriptの導入は、最初は壁を感じるかもしれませんが、一度慣れてしまえば「これなしでは開発できない」と感じるほど強力な味方になります。今回紹介したパターンは、実際の現場で最も頻繁に使われるものばかりですので、ぜひ自分のコードに組み込んで、エラーのない快適なコーディング体験を手に入れてください。

先生と生徒の振り返り会話

生徒

「先生、ありがとうございました!イベントハンドラの型定義、最初は難しそうだと思っていましたが、基本の型が決まっていることが分かって少し安心しました。」

先生

「それは良かったです。最初は ChangeEventHandlerMouseEventHandler などの名前を覚えるのが大変かもしれませんが、使っているうちに出番が多いものは自然と身についていきますよ。」

生徒

「さっきのログインフォームのコードで、HTMLInputElement | HTMLSelectElement のように縦棒(|)を使っているところがありましたね。あれはどういう意味ですか?」

先生

「鋭いですね!それは『ユニオン型』と言って、『input要素か、もしくはselect要素のどちらか』を指しています。一つの関数で複数の要素を扱いたい時には、こうして型を広げてあげることができるんです。」

生徒

「なるほど!柔軟に指定できるんですね。今までなんとなく any 型を使って逃げていた部分もあったのですが、これからはしっかり型を指定して、エディタに助けてもらいながら書いてみます。」

先生

「素晴らしい意気込みですね。any を卒業することが、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のフォーム処理でよくあるエラーと解決法を完全解説!初心者でも安心して学べるReact入門