👌

オブジェクト配列の特定のキーの値に含まれるものしか指定できないプロパティを指定する型

2023/02/23に公開

ちょっとタイトルの日本語が怪しい気がしますが、ある程度キーワードを含めたほうがいいかと思って冗長なタイトルにしています。
コードを見たほうが早いと思うのでコードで説明します。

例えば以下のように、セレクトボックスにオブジェクトの配列を渡して、配列の各オブジェクトのvalueキーの値のどれかしかdefaultValueにいれられないようにするといった使い方を想定しています。

type Option = Readonly<{
  value: string | number
  label: string
}>
type Options = Readonly<Option[]> // DeepReadonly型があるなら使いましょう。この記事では余計なことは書きたくないのでReadonlyでやっています。
type SelectProps<List extends Options> = {
  list: List
  defaultValue: List[number]['value']
}
const Select = <List extends Options>({ list, defaultValue }: SelectProps<List>): JSX.Element => {
  return (
    <select defaultValue={defaultValue}>
      { list.map(({ value, label }) => <option key={value} value={value}>{ label }</option>) }
    </select>
  )
}

const prices = [
  {
    value: 0,
    label: '値段を選択',
  },
  {
    value: 100,
    label: '100円',
  },
  {
    value: 200,
    label: '200円',
  }
] as const satisfies Options
type Prices = typeof prices

const selectPriceProps: SelectProps<Prices> = {
    list: prices,
    defaultValue: 0, // defaultValue: 0 | 100 | 200に絞られる
}
const SelectPrice = (): JSX.Element => <Select<Prices> {...selectPriceProps} />

こんな感じです。
コンポーネントを表示するときにジェネリクスを渡せるのを知らなかったので目からうろこでした。ちょっと<>が多くて見づらい気もしますが便利ですね。

ReactとTypeScript歴が浅いので他にいい書き方があればご指摘いただけるとありがたいです。

Discussion