I am using react-select
(www.react-select.com) with TypeScript and I am getting strange errors when using options
prop. Consider this code:
import * as React from "react";
import Select, {
GroupedOptionsType,
OptionsType
} from "react-select";
type OType =
| GroupedOptionsType<{ label: string; value: string }>
| OptionsType<{ label: string; value: string }>
| undefined;
const options = [
{ label: "test1", value: "test1" },
{ label: "test2", value: "test2" }
] as OType;
const CustomSelect = () => {
return <Select options={options} />;
};
Typescript is showing this:
No overload matches this call.
Overload 1 of 2, '(props: Readonly<{ [x: string]: any; [x: number]: any; defaultInputValue?: string | undefined; defaultMenuIsOpen?: boolean | undefined; defaultValue?: ValueType<GroupType<{ label: string; value: string; }>>; ... 62 more ...; tabSelectsValue?: boolean | undefined; }>): StateManager<...>', gave the following error.
Type 'OType' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>> | GroupedOptionsType<GroupType<{ label: string; value: string; }>> | undefined'.
Type 'OptionsType<{ label: string; value: string; }>' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>> | GroupedOptionsType<GroupType<{ label: string; value: string; }>> | undefined'.
Type 'OptionsType<{ label: string; value: string; }>' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>>'.
Property 'options' is missing in type '{ label: string; value: string; }' but required in type 'GroupType<{ label: string; value: string; }>'.
Overload 2 of 2, '(props: { [x: string]: any; [x: number]: any; defaultInputValue?: string | undefined; defaultMenuIsOpen?: boolean | undefined; defaultValue?: ValueType<GroupType<{ label: string; value: string; }>>; ... 62 more ...; tabSelectsValue?: boolean | undefined; }, context?: any): StateManager<...>', gave the following error.
Type 'OType' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>> | GroupedOptionsType<GroupType<{ label: string; value: string; }>> | undefined'.
Type 'OptionsType<{ label: string; value: string; }>' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>> | GroupedOptionsType<GroupType<{ label: string; value: string; }>> | undefined'.
Type 'OptionsType<{ label: string; value: string; }>' is not assignable to type 'OptionsType<GroupType<{ label: string; value: string; }>>'.ts(2769)
But when I change the order of the types in the union type and put OptionsType<>
first, it is totally ok.
import * as React from "react";
import Select, {
GroupedOptionsType,
OptionsType
} from "react-select";
type OType =
| OptionsType<{ label: string; value: string }>
| GroupedOptionsType<{ label: string; value: string }>
| undefined;
const options = [
{ label: "test1", value: "test1" },
{ label: "test2", value: "test2" }
] as OType;
const CustomSelect = () => {
return <Select options={options} />;
};
AFAIK order of types in a union type doesn't matter, but I suspect maybe it matters when using generics when type resolution happens, but I don't know. Strangely, I also did this (which is the same as above, but here I take options
directly from the SelectProps
), and it fails too:
import * as React from "react";
import Select, {
Props as SelectProps,
} from "react-select";
type OType = Pick<SelectProps<{label: string; value: string}>, 'options'>
const options = [
{ label: "test1", value: "test1" },
{ label: "test2", value: "test2" }
] as OType;
const CustomSelect = () => {
return <Select options={options} />;
};
I've modified react-select like this and it works in any way you want to, in any way. Test it. I've also implemented Select All at once , when using multiple props set to true.
import clsx from 'clsx';
import React, { ComponentProps, FC, useState } from 'react';
import ReactSelect from 'react-select';
type Option = string | number;
type Options = { [key in Option]: any };
export interface SelectProps extends ComponentProps<typeof ReactSelect> {
allowSelectAll?: boolean;
allOption?: { value: string; label: string };
options?: Options[];
onChange?: (Options) => void;
}
const Select: FC<SelectProps> = function ({
className,
options,
onChange,
allowSelectAll,
...props
}) {
const [allOption, setallOption] = useState({ value: "*", label: "Select All" });
if (allowSelectAll) {
return (
<ReactSelect
{...props}
classNamePrefix="custom-select"
className={clsx("custom-select", className)}
options={[allOption, ...options]}
onChange={selected => {
if (
selected !== null &&
selected.length > 0 &&
selected[selected.length - 1].value === allOption.value
) {
setallOption({ value: "", label: "All Selected" });
return onChange(options);
}
setallOption({ value: "", label: "Select All" });
return onChange(selected);
}}
/>
);
}
return (
<ReactSelect
{...props}
options={options}
onChange={onChange}
classNamePrefix="custom-select"
className={clsx("custom-select", className)}
/>
);
};
export default Select;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With