にわかTypeScripterによるReactでよく使うっぽい型定義まとめ

## はじめに
4月からTypeScriptとReactを実務で使い始めました。
それまではJavaメインで、JavaScriptはjQueryとかしか書いていませんでした。
なので始めたてのひよっこTypeScripterです。

少しずつ覚えてきてはいますが、まだまだわからないことだらけです。

あれ、あの型って何使えばいいんだっけ、何度もググることが多いので覚書としてよく使うであろう型定義をまとめてみました。

## コンポーネント関連の型
コンポーネントを定義するときに使うであろう型を確認します。

### 関数コンポーネントの型
#### 型定義
`React.FC<P>`
または
`React.FunctionComponent<P>`

`FC`は`FunctionComponent`の別名です。
`P`はpropsの型を定義します。

#### 使用例
```react:MyComponent.tsx
import React from 'react';

type Props = {
  name: string;
  age: number;
};
const MyComponent: React.FC<Props> = ({ name, age }) => {
  return (
    <h1>
      {name}さん({age}才)
    </h1>
  );
};

export default MyComponent;
```

### childrenの型
#### 型定義
`React.ReactNode`
基本的にpropsの型は自身で決められますが、childrenだけは上記の型を使う必要があります。

#### 使用例
```react:MyComponent.tsx
import React from 'react';

type Props = {
  title: string;
  children: React.ReactNode;
};
const MyComponent: React.FC<Props> = ({ title, children }) => {
  return (
    <>
      <h1>{title}</h1>
      {children}
    </>
  );
};

export default MyComponent;
```

### propsを使ってhtmlタグの属性を指定するときの型
これは正直知らなかったのですが、特定の属性を持ったタグを用意したい場合に便利です。

#### 型定義
`React.HTMLAttributes<T>`
`HTMLAttributes`はそのまま使うより、`ButtonHTMLAttributes`や`InputHTMLAttributes`など、htmlのタグごとに用意されている型を使うほうが、より限定できるので望ましいです。

`T`はhtmlの要素が入ります。
`ButtonHTMLAttributes`なら`HTMLButtonElement`を指定します。

#### 使用例
```react:MyComponent.tsx
import React from "react";

type Props = {
  title: string;
  attrs: React.ButtonHTMLAttributes<HTMLButtonElement>;
};
const MyComponent: React.FC<Props> = ({ title, attrs }) => {
  return (
    <>
      <h1>{title}</h1>
      <button {...attrs}>ボタン</button>
    </>
  );
};

export default MyComponent;
```
`button`タグの属性をpropsを通して渡すことができます。

このコンポーネントを使用する場合は以下のようになります。
```react:main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import MyComponent from "./MyComponent.tsx";

const buttonAttrs: React.ButtonHTMLAttributes<HTMLButtonElement> = {
  type: "button",
  name: "myButton",
};

ReactDOM.createRoot(document.getElementById("root")!).render(
  <MyComponent attrs={buttonAttrs} title="タイトル" />
);
```
propsとして渡すオブジェクトの型も属性ごとの`HTMLAttributes`を使って指定することで、不正な属性が混入することなく、動的にhtmlタグの属性の制御ができます。

これは覚えておいて損はなさそうです。

## React Hooks関連の型
### useReducerで使う型
ちょっと複雑ですが、しっかり型定義するとVS Codeなどでは入力補完してくれたりするので、より便利に使えるようになります。

#### 型定義
`React.Reducer<S,A>`
`useReducer`の第1引数に設定する処理に対して使用します。
`S`は処理内で使用する`state`、`A`は処理内で使用する`action`の型を設定します。

#### 使用例

```react:MyComponent.tsx
import React, { useReducer } from "react";

// stateの型
type State = { count: number };

// actionの型
type Action = { type: "increment" } | { type: "decrement" };

// useReducerの第2引数に設定する初期値
const initialState: State = { count: 0 };

// 今回紹介した型
const reducer: React.Reducer<State, Action> = (state, action) => {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      return state;
  }
};

const MyComponent: React.FC = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <div>Count: {state.count}</div>
      <button onClick={() => dispatch({ type: "increment" })}>+</button>
      <button onClick={() => dispatch({ type: "decrement" })}>-</button>
    </div>
  );
};

export default MyComponent;
```
`useReducer`に設定する`reducer`の型を厳密に定義したことで、`state`、`dispatch`も内部で型推論されるため、値の使用や設定がスムーズに行えるようになります。

### useStateに設定する型
これは型というよりもジェネリクスの話になりますが、ユーザー定義の型でuseStateを使いたい場合に有効です。

#### 型定義
`useState<S>`
`S`は`state`の型を設定します。
`string`や`number`などのプリミティブ型の場合は適切に推論してくれるので設定不要です。

#### 使用例
```react:MyComponent.tsx
import React, { useState } from "react";

type User = {
  name: string;
  age: number;
  country: string;
};

const MyComponent: React.FC = () => {
  const [state, setState] = useState<User>({
    name: "John",
    age: 22,
    country: "America",
  });
  return (
    <div>
      <div>{state.name}</div>
      <button
        onClick={() =>
          setState({
            name: "Kevin",
            age: 20,
            country: "Canada",
          })
        }
      >
        ボタン
      </button>
    </div>
  );
};

export default MyComponent;
```
`User`型をジェネリクスに設定しています。
これでこの`state`は`User`型しか受け付けなくなるので、不正な値を入れる心配がなくなります。

## イベントの型
`input`タグの`onChange`属性や、`form`タグの`onSubmit`属性などに設定する関数で受け取る`event`にも適切な型があります。

### changeイベント
#### 型定義
`React.ChangeEvent<T>`
`T`にはHTML要素が入ります。これを適切に設定しないと、意図した値を取得できません。

#### 使用例
```react:MyComponent.tsx
import React from "react";

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  console.log(event.target.value);
};

const MyComponent: React.FC = () => {
  return <input type="text" onChange={handleChange} />;
};

export default MyComponent;
```
ここではHTMLの要素として`HTMLInputElement`を指定しました。
これにより、`input`タグに関連する値が`event.target`から取得できるようになります。

### フォームの送信イベント
フォーム送信時、既存のsubmit処理になにか噛ませたりすることはよくあります。

#### 型定義
`React.FormEvent<T>`
changeイベントのときと同様、`T`にはHTMLの要素を入れます。

#### 使用例
```react:MyComponent.tsx
import React from "react";

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
  event.preventDefault();
  console.log("submit done");
};

const MyComponent: React.FC = () => {
  return <form onSubmit={handleSubmit}></form>;
};

export default MyComponent;
```
今回はFormタグなので`HTMLFormElement`を`T`として設定しました。

### その他のイベント
ほかにもMouseEventやKeyboardEvent、FocusEventなど、いろいろなイベントが用意されています。
基本的な使い方は同じです。型を定義する際にHTMLの要素もジェネリクスに指定します。

## まとめ
あれなんだっけな、といちいち調べるのが面倒だったので、ざーっとまとめてみました。
今回は「@types/react」モジュールの「index.d.ts」ファイルの中身をClaude AIに読み込ませ、その中で重要そうなものをピックアップして貰う形で記事を作成しました。

※重要そうな型をピックアップしてもらっただけなので、記事全体は自身が責任をもって執筆しています。

propsを使ってhtmlタグの属性を指定する方法などはまったく知らなかったので良い学びになりました。

まだTypeScriptやり始めなので、もしかするともっとこういう型があるとか、これは使わないよ、とかがあるかもしれません。
その際はぜひ教えていただけますとありがたいです。