reactjs - Typen 'string' kan inte tilldelas typen '"menu" | "selectedMenu" | undefined'


Jag gör ett flervalsval i TypeScript, Material-UI, React. Jag behöver sätta MenuProps.variant='menu', men jag stöter på felet,

Typen ''{ variant: string; PaperProps: { style: { maxHeight: number; width: number; }; }; }'' kan inte tilldelas typen ''Partial''. Typerna för egenskapen ''variant'' är inkompatibla. Typen ''string'' kan inte tilldelas typen ''"menu" | "selectedMenu" | undefined'.

för koden nedan. Hur löser man detta fel?

import React from 'react';
import Input from '@material-ui/core/Input';
import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';

const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
  variant: 'menu',
  PaperProps: {
    style: {
      maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
      width: 250,
    },
  },
};

const names = [
  'Oliver Hansen',
  'Van Henry',
  'April Tucker',
  'Ralph Hubbard',
  'Omar Alexander',
  'Carlos Abbott',
  'Miriam Wagner',
  'Bradley Wilkerson',
  'Virginia Andrews',
  'Kelly Snyder',
];


export default function MultipleSelect() {
  const classes = useStyles();
  const theme = useTheme();
  const [personName, setPersonName] = React.useState<string[]>([]);

  const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
    setPersonName(event.target.value as string[]);
  };

  return (
        <Select
          multiple
          value={personName}
          onChange={handleChange}
          input={<Input />}
          MenuProps={MenuProps}
        >
          {names.map((name) => (
            <MenuItem key={name} value={name} style={getStyles(name, personName, theme)}>
              {name}
            </MenuItem>
          ))}
        </Select>
      )
}

Referens
https://material-ui.com/api/menu/
https://material-ui.com/components/selects/#multiple-select

Svar #1

Eftersom variant endast tar emot typen "menu" | "selectedMenu" | undefined. Men du skickar ett värde som är "menu" utan typ. Så det kommer automatiskt att ha typen string. Du behöver definiera en typ för variant. Så här:

const MenuProps = {
  variant: 'menu' as 'menu',
  ...
};

Svar #2

Du kan importera typen MenuProps från Material-UI med:

import { MenuProps as MenuPropsType } from "@material-ui/core/Menu";

Då kan du använda detta på följande sätt:

const MenuProps: Partial<MenuPropsType> = {
  variant: "menu",
  PaperProps: {
    style: {
      maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
      width: 250
    }
  }
};

Du använder Partial<MenuPropsType> (som det också görs i Select-typdefinitionen) eftersom Select automatiskt lägger till den obligatoriska open-egenskapen (om du tar bort Partial, kommer det att klaga på att open-egenskapen inte är specificerad).

Här är ett fungerande exempel baserat på din kod:

import React from "react";
import { MenuProps as MenuPropsType } from "@material-ui/core/Menu";
import Input from "@material-ui/core/Input";
import MenuItem from "@material-ui/core/MenuItem";
import Select from "@material-ui/core/Select";

const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps: Partial<MenuPropsType> = {
  variant: "menu",
  PaperProps: {
    style: {
      maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
      width: 250
    }
  }
};

const names = [
  "Oliver Hansen",
  "Van Henry",
  "April Tucker",
  "Ralph Hubbard",
  "Omar Alexander",
  "Carlos Abbott",
  "Miriam Wagner",
  "Bradley Wilkerson",
  "Virginia Andrews",
  "Kelly Snyder"
];

export default function MultipleSelect() {
  const [personName, setPersonName] = React.useState<string[]>([]);

  const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
    setPersonName(event.target.value as string[]);
  };

  return (
    <Select
      multiple
      value={personName}
      onChange={handleChange}
      input={<Input />}
      MenuProps={MenuProps}
    >
      {names.map((name) => (
        <MenuItem key={name} value={name}>
          {name}
        </MenuItem>
      ))}
    </Select>
  );
}