🫐

keyofとtypeofを活用したチェックボックスのデータ管理

2024/02/10に公開

下記のようにkeyoftypeofを組み合わせて、UserInfoValueのような型を用意する場面があると思います。

const userInfo = {
    name: "John",
    age: 23,
} as const;

type UserInfoValue = typeof userInfo[keyof typeof userInfo];

今回は上記の型を用いて、個人的に良いなと思った使い所を簡単なチェックボックスを例にしてまとめていきたいと思います。

チェックボックス例

チェックボックスを実装する際、必要になるデータは基本的に描画値(label名)とAPIに渡す値(value値)になると思います。

下記のチェックボックスでは、
描画値が「レモン、リンゴ、オレンジ」で、APIに渡す値が「lemon、apple、orange」です。

何も考えずに簡単に実装していく場合、チェックボックスのデータ管理は下記のようになります。

fruits.ts
export const fruits = [
  {
    label: "レモン",
    value: "lemon",
  },
  {
    label: "リンゴ",
    value: "apple",
  },
  {
    label: "オレンジ",
    value: "orange",
  },
] as const;

これをkeyoftypeofを活用したデータ管理に変えていきます。

keyoftypeofを活用したデータ管理

定数fruitskeyに適当な値、valueにチェックボックスのvalue値を定義しています。

Fruits型がkeyoftypeofを組み合わせて定義した型になっています。

定数fruitsToScreenNamekeyにチェックボックスのvalue値、valueにチェックボックスのlabel名を定義しています。

fruits.ts
export const fruits = {
  LEMON: "lemon",
  APPLE: "apple",
  ORANGE: "orange",
} as const;

export type Fruits = typeof fruits[keyof typeof fruits];

export const fruitsToScreenName: { [key in Fruits]: string } = {
  [fruits.LEMON]: "レモン",
  [fruits.APPLE]: "アップル",
  [fruits.ORANGE]: "オレンジ",
};

この定義をコンポート側で使用すると下記のようになります。
(※サンプルとしてのコードなので愚直にそのまま書いています。)

↓入力フォーム画面で使用するチェックボックス

EntryFruitsCheckbox.tsx
import { fruits, fruitsToScreenName } from "./fruits.ts"

export const EntryFruitsCheckbox: React.FC = () => {
  return (
    <div>
      {fruits.map((fruit) => (
        <>
          <input
            key={fruit.value}
            id={fruit.value}
            value={fruit.value}
            // チェック状態とその更新は割愛
            // checked={}
            // onChange={}
            disabled={disabled}
          />
          <label for={fruit.value}>{fruitsToScreenName[fruit.value]}</label>
        </>
      ))}
    </div>
  )
}

↓入力確認フォーム画面で使用するチェックボックス

ConfirmFruitsCheckbox.tsx
import { fruitsToScreenName, Fruits } from "./fruits.ts"

type ConfirmFruitsCheckboxProps = {
  fruitsValues: Fruits
}

export const ConfirmFruitsCheckbox: React.FC<ConfirmFruitsCheckboxProps> = (props) => {
  return (
    <div>
      {props.fruitsValues.map((fruitsValue) => (
        <span>{fruitsToScreenName[fruitsValue]}</span>
      ))}
    </div>
  )
}

fruitsToScreenName[fruitsValue]fruitsToScreenNameに型を付与しているため、期待する値だけに絞ることができるのと、
label名を参照しにいくだけというシンプルな構造になっています。

また、Fruits型に関しては、StoreやAPIリクエストメソッドなどにも活用できるため汎用性のある型になっています。

まとめ

keyoftypeofを組み合わせた型がどのような場面で活用できるのか少しでもイメージできたら幸いです。

他にも活用できる場面が出てくると思うので考えていきたいと思います。

Discussion