14

I am using Typescript and Material-UI I want to declare the component type for a variable like this

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

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

But I am getting the error:

[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'.

This is how the SvgIcon.ts looks like. What am I doing wrong?

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;
7
  • What are you trying to achieve? <MoreVert /> is a ReactNode type, has nothing to do with props, it's already applied. You might wanted something like myIcon = MoreVert without application Commented Sep 27, 2018 at 14:39
  • @Ebuall I am using typescript so I want to declare the type of it. Commented Sep 27, 2018 at 18:20
  • But you want to declare completely unrelated type. Commented Sep 27, 2018 at 18:22
  • 2
    @Ebuall That's why the question is here. Commented Sep 27, 2018 at 18:29
  • It just makes no sense. MoreVert already has type React.ComponentType<SvgIconProps>, <MoreVert /> has type Element, and has nothing in common with props, you already applied props at this point. Commented Sep 27, 2018 at 18:36

4 Answers 4

17

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

By default the result of a JSX expression is typed as any. You can customize the type by specifying the JSX.Element interface. However, it is not possible to retrieve type information about the element, attributes or children of the JSX from this interface. It is a black box.

The reason why I lose all type information with JSX.Element is because it extends React.ReactElement<any> which has the type of any. To fix this I used it like this

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

Now I have the element with all the type information.

Sign up to request clarification or add additional context in comments.

1 Comment

The SvgIconProps interface can be imported via: import { SvgIconProps } from "@material-ui/core/SvgIcon";
5

If anyone does not work by the way answered question of @Murat Karagöz you may try this when initializing an interface or a variable of an Icons from Material UI using TypeScript.

I got this working by declaring like this:

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',
  },
...
];

Reference: [Docs & Types] Importing icons from @material-ui/icons in TypeScript #647

Comments

2

As already briefly described by Ebuall in a comment, here's how you would declare the variable depending on whether you want the JSX element or the component type:

let myIconElement: JSX.Element = <MoreVert />;
let MyIconComponent: React.ComponentType<SvgIconProps> = MoreVert;

// Example component that uses the icon
function myComponent(props: {}) {
    return <>
        {myIconElement}
        {<MyIconComponent />}
    </>;
}

Comments

0

<MoreVert /> is a component.

SvgIconProps just define the list of props passed to this component.

You should try:

let myIcon: SvgIcon = <MoreVert />;

3 Comments

I tried that but the ts compiler complains that he can not find SvgIcon even with the import import SvgIcon from '@material-ui/core/SvgIcon/SvgIcon';
Wierd, because it's exported. So maybe React.ComponentType<SvgIconProps> ?
I also tried that it will lead to Type 'Element' provides no match for the signature '(props: SvgIconProps & { children?: ReactNode; }, context?: any): ReactElement<any>'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.