Material-ui: [Autocomplete] Wrong T inference

Created on 30 Jan 2020  路  13Comments  路  Source: mui-org/material-ui

I just updated to last lap version 4.0.0-alpha.40 which broke my <Autocomplete /> component so I'm trying to adapt to the changes. However I can figure out how to do it.

I've made a codesandbox example (code below):

import * as React from "react";
import { Autocomplete } from "@material-ui/lab";
import TextField from "@material-ui/core/TextField";

interface Person {
  firstName: string;
  lastName: string;
}

const initialValues: Person[] = [{ firstName: "John", lastName: "Doe" }];
const options: Person[] = [
  { firstName: "John", lastName: "Doe" },
  { firstName: "Jane", lastName: "Doe" }
];

export default function App() {
  const [values, setValues] = React.useState(initialValues);
  const handleSelect = (e: any, v: Person[]) => {
    setValues(v);
  };

  return (
    <div>
      <Autocomplete
        multiple
        options={options}
        getOptionLabel={option => option.firstName}
        value={values}
        onChange={handleSelect}
        renderInput={params => (
          <TextField {...params} label="Persons" fullWidth />
        )}
      />
    </div>
  );
}

It seems that options and onChange disagree on the types.

Autocomplete typescript

All 13 comments

Changing (e: any, v: Person[]) to (e: any, v: any) fixes it but I assume it could be handled better

And changing the component to freeSolo with no options breaks it too.

<Autocomplete
  multiple
  freeSolo
  value={values}
  onChange={handleSelect}
  renderInput={params => (
    <TextField {...params} label="Persons" fullWidth />
  )}
/>

Curious. cc @testarossaaaaa.

@mr-bjerre It seems that the whole Person[] from handleSelect inferred as T type and then T[] unwraps to Person[][]. I need time to figure out a solution. As a quick fix you can explicitly specify the correct type for the component:

<Autocomplete<Person> multiple ... />

or inline the change handler:

<Autocomplete ... onChange={(e, v) => setValues(v)} />

Ah yes that'll work thanks

I don't think this issue should be closed. I'm having the same problem with it: it doesn't infer the right type for the _option_.

interface MyOption {
    someProp: number;
    someOtherProp: string;
}

const options: MyOption[] = [ /*...*/ ];

return (
    <Autocomplete
        options={options}
    />
);

In the example above, the component is going to infer MyOption[][] instead of MyOption[]. Although the suggested workaround makes the code compile again, it just feels weird and I believe it should be fixed in future versions.

This worked until 4.0.0-alpha-39 and stopped working with 4.0.0-alpha-40.

Do you have a reproduction?

@oliviertassinari for some reason, I can't get @akharkhonov 's example to fail, even after removing the explicit generic parameter, but in @mr-bjerre 's example, just change const handleSelect = (e: any, v: any]) => { to const handleSelect = (e: any, v: Person[]) => { and you'll be able to see it.

@andreivanea Type something into the textfield, press Enter and press button Print. You will see fail.

@akharkhonov I get it now. I thought you were trying to point out something else. Your example shows a runtime error, while I was talking about a compile-time one (TypeScript complains about incompatible types).

I am having this issue using the onChange function of an autocomplete with multiple = true. Hope this is the right place to post.

<Autocomplete
      multiple
      options={users} // TeamMember[]
      renderInput={params =><TextField {...params} /> }
      onChange={handleChange}
      getOptionLabel={option => option.firstName + " " + option.lastName}
    />

Seems multiple is messing up the type inference. So if my options is an array, the onchange value is not an array, right? So handleChange should be (event: any, value: TeamMember | null) => void; But it infers the type TeamMember[] for value. However, if I provide TeamMember[] in the onChange it infers TeamMember[][] for options. So there is no way to make that work.

Commenting out multiple or onChange fixes it for Typescript.

Specifying the type <Autocomplete<TeamMember> ... seems good but then TeamMember[] is inferred in event value. But it shouldn't give an array for the value, should it?

EDIT: Actually an array is the correct type. So this is the current way to do it. But the problem still persists.

https://github.com/mui-org/material-ui/pull/20949 fixes issue described in the first comment without having to specify explicit value type.

Issue described by @akharkhonov is something separate I believe.

Was this page helpful?
0 / 5 - 0 ratings