What is wrong in the following code?
TS2322: Type '(event: SelectChangeEvent) => void' is not assignable to type '(event: SelectChangeEvent<unknown>, child: ReactNode) => void'. Types of parameters 'event' and 'event' are incompatible.
Type 'SelectChangeEvent<unknown>' is not assignable to type 'SelectChangeEvent<string>'.
Type 'Event & { target: { value: unknown; name: string; }; }' is not assignable to type 'SelectChangeEvent<string>'.
Type 'Event & { target: { value: unknown; name: string; }; }' is not assignable to type 'Event & { target: { value: string; name: string; }; }'.
Type 'Event & { target: { value: unknown; name: string; }; }' is not assignable to type '{ target: { value: string; name: string; }; }'. The types of 'target.value' are incompatible between these types.
Type 'unknown' is not assignable to type 'string'.
Select.d.ts(104, 3): The expected type comes from property 'onChange' which is declared here on type 'IntrinsicAttributes & { items: { children: ReactNode; props: MenuItemProps<"li", {}>; }[]; } & SelectProps<unknown>'
import * as React from 'react';
import MuiSelect, {SelectProps as MuiSelectProps} from '@mui/material/Select';
import MuiMenuItem, {MenuItemProps as MuiMenuItemProps} from '@mui/material/MenuItem';
export type SelectProps<T = unknown> = {
items: {
children: React.ReactNode,
props: MuiMenuItemProps,
}[],
} & MuiSelectProps<T>;
const Select: React.FC<SelectProps> = ({items, ...props}) => {
return (
<MuiSelect
{...props}
>
{
items.map((item, index) => (
<MuiMenuItem key={item.props.key ?? index} {...item.props}>{item.children}</MuiMenuItem>
))
}
</MuiSelect>
);
};
export default Select;
This is the onChange
prop
const handleChange = (event: SelectChangeEvent) => {
// Some logic
};
CodePudding user response:
Calling SelectChangeEvent
with no type parameter will result in the default value, string
(see below), which is not compatible with the inferred type unknown
- what you get when calling your Select
component. You can fix this by using SelectChangeEvent<unknown>
in handleChange
.
Explanation
The trouble T
type parameter passed to MuiSelectProps
is the culprit. Looking at Select.d.ts, T
is used here:
onChange?: SelectInputProps<T>['onChange'];
Which points to
/**
* The change can be caused by different kind of events.
* The type of event depends on what caused the change.
* For example, when the browser auto-fills the `Select`
you'll receive a `React.ChangeEvent`.
*/
export type SelectChangeEvent<T = string> =
| (Event & { target: { value: T; name: string } })
| React.ChangeEvent<HTMLInputElement>;
export interface SelectInputProps<T = unknown> {
// ...
onChange?: (event: SelectChangeEvent<T>, child: React.ReactNode) => void;
So when you call SelectChangeEvent
sans a type parameter, it defaults to string
while unknown
is inferred as the default type parameter for all the parent usages.
Here's a playground with this.