I'd like to have a CustomSelect React component that works with any predefined set of options and have TypeScript warn users when an unknown option is used.
Here is my attempt:
type Props<Value> = {
value: Value;
onChange: (newValue: Value) => void;
options: readonly string[];
};
function CustomSelect<Value>({
value,
onChange,
options
}: Props<Value>) {
return (
<select
value={value /* See Issue 1 below */}
onChange={(e) => {
onChange(e.target.value); // See Issue 2 below
}}
>
{options.map((value) => (
<option value={value} key={value}>
{value}
</option>
))}
</select>
);
}
Usage:
const FRUITS = ["apple", "banana", "melon"] as const;
type Fruit = typeof FRUITS[number];
<CustomSelect<Fruit> {/* See Bonus question below */}
value={state.fruit}
onChange={(newFruit) => { ... }}
options={FRUITS}
/>
This has two TypeScript issues:
Issue 1
Type 'Value' is not assignable to type 'string | number | readonly string[] | undefined'.
Issue 2
Argument of type 'string' is not assignable to parameter of type 'Value'.
Bonus question
Is it absolutely necessary to pass <Value> to the CustomSelect, or can CustomSelect somehow deduct this Value from the provided options?