I use react-select
in my project.
App.tsx
import "./styles.css";
import React, { useState } from "react";
import Select, { components, OptionProps } from "react-select";
const options = [
{
label: "label 1",
value: "value 1",
dialCode: "dialCode 1"
},
{
label: "label 2",
value: "value 2",
dialCode: "dialCode 2"
}
];
const { Option } = components;
const IconOption = (props: any) => {
const { label, dialCode } = props.data;
return (
<Option {...props}>
<div>{label}</div>
<div>{`( ${dialCode})`}</div>
</Option>
);
};
export default function App() {
const [selected, setSelected] = useState(options[0]);
return (
<Select
options={options}
value={selected}
components={{ Option: IconOption }}
/>
);
}
I use any
type in
const IconOption = (props: any) => {
const { label, dialCode } = props.data;
return (...);
};
When I set the type of the props
to OptionProps
, typescript throws error.
const IconOption = (props: OptionProps) => {
const { label, dialCode } = props.data;
return (...);
};
How to fix it?
Codesandbox
https://codesandbox.io/s/react-typescript-forked-mjo74r?file=/src/App.tsx:0-1069
CodePudding user response:
OptionProp
is a generic type. You should declare custom type for option's data and pass it to generic.
type OptionData = {
label: string;
value: string;
dialCode: string
}
const options: OptionData[] = [
{
label: "label 1",
value: "value 1",
dialCode: "dialCode 1"
},
{
label: "label 2",
value: "value 2",
dialCode: "dialCode 2"
}
];
const { Option } = components;
const IconOption = (props: OptionProps<OptionData>) => {
const { label, dialCode } = props.data;
return (
<Option {...props}>
<div>{label}</div>
<div>{`( ${dialCode})`}</div>
</Option>
);
};
Update 1: the ideomatic way to handle union types in TS is adding type predicates:
function isMultiOption<T>(value: MultiValue<T> | SingleValue<T>): value is T[] {
return Array.isArray(value)
}
function isSingleOption<T>(value: MultiValue<T> | SingleValue<T>): value is T {
return value != null && !isMultiOption(value)
}
const onSelectedChange = (
newValue: MultiValue<OptionData> | SingleValue<OptionData>
) => {
if (newValue == null) {
return
}
if (isMultiOption(newValue)) {
setSelected(newValue[0]);
} else if (isSingleOption(newValue)) {
setSelected(newValue)
}
};