3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Qiita株式会社Advent Calendar 2024

Day 18

Select系コンポーネントでvalueの型を厳密にする

Last updated at Posted at 2024-12-17

この記事の概要

Selectコンポーネントを自作しようとして、defaultValueとoptionとして渡ってくる要素のvalueが一致していないとエラーが出るようにしたかったです。

備忘録がてら記事にしました。

環境

TypeScript 5.4以降
(記事内で使っているNoInferはTypeScriptの5.4から使用できます)

実装

import { ComponentProps } from "react";

type SelectOption<T extends string> = {
  label: string;
  value: T;
};

type Props<T extends string> = ComponentProps<"select"> & {
  defaultValue?: NoInfer<T>;
  label: string;
  options: readonly SelectOption<T>[];
  placeholder?: string;
};

export function Select<T extends string>({
  defaultValue,
  label,
  options,
  ...props
}: Props<T>) {
  return (
    <div>
      <label>{label}</label>
      <select
        defaultValue={defaultValue ?? ""}
        {...props}
      >
        {placeholder ? (
          <option value="" disabled>
            {placeholder}
          </option>
        ) : null}
        {options.map((option) => (
          <option key={option.value} value={option.value}>
            {option.label}
          </option>
        ))}
      </select>
    </div>
  );
}

型に適合しない場合

例えば以下の場合はdefaultValueのpinkがoptionsのvalueの中にありません。

<Select
  label="セレクト要素のラベル"
  defaultValue="pink"
  helperText="ヘルパーテキスト"
  options={[
    { label: "Red", value: "red" },
    { label: "Blue", value: "blue" },
    { label: "Green", value: "green" },
  ]}
/>

その場合以下のように怒られます。

Type '"pink"' is not assignable to type '((string | number | readonly string[]) & ("red" | "blue" | "green")) | undefined'.
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?