javascript - Material-UI: Hur man deklarerar en typ för React.ComponentType<P> med TypeScript


Jag använder Typescript och Material-UI. Jag vill deklarera komponenttypen för en variabel på det här sättet

import MoreVert from '@material-ui/icons/MoreVert'
import { SvgIconProps } from '@material-ui/core/SvgIcon';

let myIcon: SvgIconProps = <MoreVert />; // does not work

Men jag får felet:

[ts]
Type 'Element' is not assignable to type 'SvgIconProps'.
  Types of property 'type' are incompatible.
    Type 'string | ComponentClass<any> | StatelessComponent<any>' is not assignable to type 'string'.
      Type 'ComponentClass<any>' is not assignable to type 'string'.

Så här ser SvgIcon.ts ut. Vad gör jag för fel?

import * as React from 'react';
import { StandardProps, PropTypes } from '..';

export interface SvgIconProps
  extends StandardProps<React.SVGProps<SVGSVGElement>, SvgIconClassKey> {
  color?: PropTypes.Color | 'action' | 'disabled' | 'error';
  component?: React.ReactType<SvgIconProps>;
  fontSize?: 'inherit' | 'default' | 'small' | 'large';
  nativeColor?: string;
  titleAccess?: string;
  viewBox?: string;
}

export type SvgIconClassKey =
  | 'root'
  | 'colorSecondary'
  | 'colorAction'
  | 'colorDisabled'
  | 'colorError'
  | 'colorPrimary'
  | 'fontSizeInherit'
  | 'fontSizeSmall'
  | 'fontSizeLarge';

declare const SvgIcon: React.ComponentType<SvgIconProps>;

export default SvgIcon;

Svar #1

Referens: https://www.typescriptlang.org/docs/handbook/jsx.html

Som standard typas resultatet av ett JSX-uttryck som any. Du kan anpassa typen genom att ange JSX.Element-gränssnittet. Det är dock inte möjligt att hämta typinformation om elementet, attributen eller barnen av JSX från detta gränssnitt. Det är en svart låda.

Anledningen till att jag förlorar all typinformation med JSX.Element är för att det utökar React.ReactElement<any> som har typen any. För att åtgärda detta använde jag det på detta sätt

 let myIcon: React.ReactElement<SvgIconProps> = <MoreVert />; 

Nu har jag elementet med all typinformation.

Svar #2

Om någon inte arbetar på sättet som besvarade frågan från @Murat Karagöz kan du prova detta när du initialiserar ett gränssnitt eller en variabel av en Ikoner från Material UI med TypeScript.

Jag fick detta att fungera genom att deklarera på detta sätt:

import ShowChartIconOutlined from '@material-ui/icons/ShowChartOutlined';
import { SvgIconProps } from '@material-ui/core';

type Menu = {
  id: number;
  icon: (props: SvgIconProps) => JSX.Element;
  label: string;
}[];

const NavBarMenus: Menu = [
  {
    id: 1,
    icon: ShowChartIconOutlined,
    label: 'Dashboard',
  },
...
];

Referens: [Docs & Typer] Importera ikoner från @material-ui/icons i TypeScript #647

Relaterade artiklar