material-ui icon indicating copy to clipboard operation
material-ui copied to clipboard

`<Select />`'s `onChange` does not follow the type that I specify

Open scallaway opened this issue 3 years ago • 10 comments

Duplicates

  • [X] I have searched the existing issues

Latest version

  • [X] I have tested the latest version

Current behavior 😯

When supplying an onChange handler to the <Select /> component, the resulting type for event.target.value is always string, even if I specify the type signature of the function to be (event: SelectChangeEvent<number>) => void;

Expected behavior 🤔

event.target.value always seems to be string rather than the type that I specify.

Steps to reproduce 🕹

Live example: https://codesandbox.io/s/affectionate-dust-bxrn7k?file=/src/App.tsx

Context 🔦

I'd expect to be able to pull out a number in the example that I have given, and this used to work on V4 but we've uncovered this problem during our migration to V5.

Your environment 🌎

No response

scallaway avatar Jul 05 '22 10:07 scallaway

Should it be casted to a number type by doing setValue(Number(event.target.value));? But then the question that arises is what is the point of providing a generic SelectChangeEvent type.

ZeeshanTamboli avatar Jul 06 '22 11:07 ZeeshanTamboli

Should it be casted to a number type by doing setValue(Number(event.target.value));?

Yeah we've just been doing event.target.value as {type} but that's far from ideal. Literally no point in the generic if we have to do that everytime

scallaway avatar Jul 06 '22 13:07 scallaway

Hey @siriwatknp I would like to work on this issue if no one else is already looking into it. Thanks!

noobyogi0010 avatar Jul 07 '22 05:07 noobyogi0010

@noobyogi0010

If you're going to tackle this, I think we need to look at the fact that SelectChangeEvent is a union of a type that's dependent on the generic, as well as React.ChangeEvent due to the auto-fill.

It doesn't look like we can pass a generic to the latter either which is a real problem.

Is there a way we can remove the fact that we're including React.ChangeEvent in the type?

scallaway avatar Jul 07 '22 11:07 scallaway

@scallaway I am unaware of any such way rn. But I am happy to do some research and get back to you on this.

noobyogi0010 avatar Jul 07 '22 11:07 noobyogi0010

I think my current issue is related to this one, but I am hesitating to reopen this. But here goes! I am using joy UI@latest

Current Behaviour

The onChange prop for the Select component has this type: onChange?: (e: React.MouseEvent | React.KeyboardEvent | React.FocusEvent | null, value: TValue | null) => void; My onChangeHandler function is typed like this

  const handleChangeRowsPerPage = (_e: null, value: string) => {
    setRowsPerPage(parseInt(value, 10));
    setPage(0);
  };

which matches null, value: TValue | null but I still get this error No overload matches this call. Overload 1 of 2, '(props: { component: ElementType<any>; } & SelectStaticProps & SelectSlotsAndSlotProps & { defaultValue?: string | null | undefined; getSerializedValue?: ((option: SelectOption<...> | null) => string | ... 2 more ... | undefined) | undefined; onChange?: ((e: MouseEvent<...> | ... 2 more ... | null, value: string | null) => void) | undefined; renderValue?: ((option: SelectOption<...> | null) => ReactNode) | undefined; value?: string | ... 1 more ... | undefined; } & Omit<...>): Element | null', gave the following error. Type '(_e: null, value: string) => void' is not assignable to type '(e: MouseEvent<Element, MouseEvent> | KeyboardEvent<Element> | FocusEvent<Element, Element> | null, value: string | null) => void'. Types of parameters '_e' and 'e' are incompatible. Type 'MouseEvent<Element, MouseEvent> | KeyboardEvent<Element> | FocusEvent<Element, Element> | null' is not assignable to type 'null'. Type 'MouseEvent<Element, MouseEvent>' is not assignable to type 'null'. Overload 2 of 2, '(props: DefaultComponentProps<SelectTypeMap<string, {}, "button">>): Element | null', gave the following error. Type '(_e: null, value: string) => void' is not assignable to type '(e: MouseEvent<Element, MouseEvent> | KeyboardEvent<Element> | FocusEvent<Element, Element> | null, value: string | null) => void'.ts(2769)

Here is what my Select looks like

   <Select
            value={String(rowsPerPage)}
            onChange={handleChangeRowsPerPage}
            indicator={<FiChevronDown className="w-10 h-10 stroke-inactive" />}
            slotProps={{
              listbox: {
                placement: 'bottom-end',
                sx: {
                  border: 'black',
                },
              },
            }}
          >

Expected Behaviour

The onChange props should not throw because my handler type matches one of the possible signatures.

Steps to Reproduce

No response

Context

No response

My Environment

No response

moody2times avatar Mar 09 '23 07:03 moody2times

@mudiagauwojeya Your issue is related to Joy UI. So, please open a new issue having a CodeSandbox reproduction. The issue template is a good starting point.

ZeeshanTamboli avatar Mar 13 '23 12:03 ZeeshanTamboli

@mudiagauwojeya Your issue is related to Joy UI. So, please open a new issue having a CodeSandbox reproduction. The issue template is a good starting point.

Already did thanks.

moody2times avatar Mar 13 '23 18:03 moody2times

@mudiagauwojeyaВаша проблема связана с пользовательским интерфейсом Joy. Итак, пожалуйста, откройте новую проблему с репродукцией CodeSandbox. Шаблон задачи является хорошей отправной точкой.

Уже сделал спасибо.

Is there already some finished result?

Vendjin avatar May 03 '23 11:05 Vendjin

Might be closed by mui/base-ui#14

siriwatknp avatar May 03 '23 15:05 siriwatknp

Still doesn't work, have the same issue

event: SelectChangeEvent<MyEnum> always cast as string

holyhlifuga avatar Aug 02 '23 09:08 holyhlifuga

Are there plans to resolve this issue in the near future?

dominikpiegdon avatar Aug 11 '23 09:08 dominikpiegdon

Problem still exists

AlekseyMalakhov avatar May 23 '24 13:05 AlekseyMalakhov

FYI: The issue still exists. What is does right now is creating a union-type of string | MyCustomType.

This is due to a connection to the native HTMLInputElement, where we have the definition: value: string. It comes from node_modules/@mui/material/Select/SelectInput.d.ts:11:

export type SelectChangeEvent<Value> =
  | (Event & { target: { value: Value; name: string } })
  | React.ChangeEvent<HTMLInputElement>;

React.ChangeEvent<HTMLInputElement> is the problem here.

misantronic avatar Jul 03 '24 21:07 misantronic