operational-ui
operational-ui copied to clipboard
Better type definition for `Select`
Problem
The type definition in the onChange
part of Select
have too many options and don't infer correctly from the options
provided to the component.
Snippet
<Select
options={[{ label: "option1", value: "option 1" }]}
onChange={value => {
console.log(value); // This should be `string` only
}}
/>
Codesandbox
This is interesting. The value
passed in the onChange
callback seems like it should be any
in order to handle cases like:
<Select
options={[
{
label: "John",
value: -10,
},
{
label: "Joey",
value: { holy: "Yes" },
},
{
label: "Tupac",
value: "true",
},
{
label: "Chandler",
value: 10,
},
]} />
We have numbers in some cases, objects in others, and strings in other cases and we don't really know which one can/will be chosen.
I thought about generics but I'm not sure we can get type safety here. Ideas?
ping @fabien0102
I think that we should be able to infer from options
even in this extreme case -> number | {holy: string} | string | number
.
After it's not an easy thing to fix 😅
Hmmm. But options is an array where value
can be anything, right? In my example,
{
label: React.ReactElement<any> | string
value: any // what would you have here?
}
value
in this case can be anything. We do not enforce a type of value. Should we? We might be able to make value T
where all values are either a string or an object of a certain shape. That might be safer actually.
We just want to infer, so T
should fit this usecase. T
will be used just to have a cross type reference, not for restrict the API 😉
You mean this?
interface SelectProps<T> {
// ... other props
options: Array<{ label: React.ReactElement<any> | string, value: T }>
}
In this case, each option
in options
' value
has to be the same type. This example will not work, right? Unless I missed something...