Creating types for React.ComponentType<P> in Material-UI using TypeScript

I am currently working with Typescript and incorporating Material-UI into my project. I am trying to define the component type for a variable as shown below:

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

let myIcon: SvgIconProps = <MoreVert />; // this code is not functioning as expected

However, I am encountering the following error message:

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

You can find the contents of the SvgIcon.ts file here. Can you help me identify what mistake I am making?

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;

Answer №1

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

When using a JSX expression, the default type assigned is any. To customize this type, you can specify the JSX.Element interface. However, it does not provide access to detailed information about the element, attributes, or children of the JSX. It remains a closed off entity.

The issue encountered with JSX.Element stems from its extension of React.ReactElement<any>, which results in a generic type of any. To address this, a different approach was taken:

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

This adjustment now allows for retaining all relevant type information within the element.

Answer №2

If you are having trouble with setting up an interface or a variable for Icons from Material UI using TypeScript, try following the example provided by @Murat Karagöz.

To make it work, declare your code 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',
  },
...
];

For more information, check out this reference: [Docs & Types] Importing icons from @material-ui/icons in TypeScript #647

Answer №3

As previously mentioned by Ebuall in a comment, here is an example of how to declare a variable based on whether you need the JSX element or the component type:

let iconElement: JSX.Element = <MoreVert />;
let IconComponent: React.ComponentType<SvgIconProps> = MoreVert;

// Sample component utilizing the icon
function myCustomComponent(props: {}) {
    return <>
        {iconElement}
        {<IconComponent />}
    </>;
}

Answer №4

<MoreVert /> represents a component.

SvgIconProps simply outlines the properties that are provided to this particular component.

Give this a shot:

let myIcon: SvgIcon = <MoreVert />;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In Javascript, merge two objects while maintaining their original references

Here's a basic illustration of my goal: data = {name: 'fred'}; newData = {}; newData.name = data.name; newData.name = 'ted'; console.log(data.name); // I expect this to be ted instead of fred I am wondering if it is feasible i ...

What are some ways to implement Node.js within Netsuite?

Recently, I've been exploring Netsuite and I'm curious to learn about the feasibility of integrating Node.js or npm modules into a SuiteScript or Suitelet. Is it possible? I have a specific aim in mind - to utilize some npm modules within Netsui ...

Unable to integrate a new third-party script into a Next.js application

In my attempt to integrate the following script, I have tried adding it first to _document.js, then to app.js, and finally to a specific page. <Script src="https://anywebsite.ai/chatbot/chatbot.js"></Script> <Script id=" ...

Struggling to display a PHP success message using AJAX

So I have this code where I am trying to create a form in PHP and send a message. The message is being submitted successfully, but I am facing an issue when it comes to displaying a success message. The page submits the data but does not show any output. H ...

Sinon.js: How to create a mock for an object initialized with the new keyword

Here is the code that I am working with: var async = require('async'), util = require('util'); var Parse = require('parse/node'); function signup(userInfo, callback) { var username = userInfo.username, email ...

Device sending incorrect JSON format

A JSON response from a device is as follows: { "Order": ""3"", "ID": ""SHEET"", "Name": ""Time Sheet"", "ConID": ""!s?d2SzxcSDW1cf$*@4812sC#"" } The property values in the JSON are enclosed in double quotes, causing them to be incorrect. Is ...

Inconsistent CSS3 transitions behavior in Firefox 4

I have been playing around with some css3 transitions and created a slider test. It works perfectly in webkit browsers, but I have noticed an issue in Firefox 4. When clicking on the left link for the first time, the slider is supposed to slide to the left ...

Highlight dates in Vue.js that are overdue using a date filter

Currently, I have a Vue filter set up to display dates in a visually appealing way. However, I am looking to enhance the filter by adding a feature that would highlight dates in red if they are overdue (meaning the date is earlier than the current date). I ...

Stopping the Game Loop in Windows Phone 8.1 with WinJS

Despite everything working smoothly, I am facing an issue with stopping the game loop when the Start button is pressed and the app is moved to the background. The event handler for suspend, app.oncheckpoint = function(args) {}, does not seem to fire for t ...

Guide to developing a universal store extension

I've been attempting to create a reactive global $store object using a plugin, but so far I have not been successful in getting it to function as intended. store.ts: import {reactive} from "vue"; export default { install: (app:any, opt ...

Mediawiki functionality experiencing issues within iframe display

Currently, I am working with MediaWiki built in PHP. Due to certain reasons, I have to embed this application within an iframe. All functionalities are running smoothly except for the Edit link for pages. The issue arises when I try to access the second li ...

"Encountered an issue while attempting to send the message: Unable to retrieve data" while utilizing NextJS and the

Currently, I am utilizing fetch along with NextJS to attempt to send information such as name, phone number, email, company, and message to an API. However, I am encountering an issue where the error message simply states 'Failed to fetch' in the ...

Incorporating a class element within an Angular 2 directive

When working with Angular 2 directives, one way to add an element is by using the following code: this._renderer.createElement(this._el.nativeElement.parentNode, 'div'); After adding the element, how can I set its class and keep a reference to ...

In what way can an array be assigned to a new key within the same key along with additional objects?

My goal is to transform the existing key value into a new format within the same key. It may be difficult for me to explain clearly through words, but the following data will help clarify. The data is currently structured as follows: const sampelData = [{ ...

Modifying the appearance of a CSS element with jQuery: Step-by-step guide

The code I have is as follows: $('.signup-form-wrapper').css("style", "display: block"); $('.login-form-wrapper').css("style", "display: none"); I'm not sure why it's not working. The current appearance of ...

Can you guide me on how to specify the return type in NestJS for the Session User in a request?

async authenticated(@Req() request: Request) { const user = request.user return user } It is important for the 'user' variable to have the correct type globally. While working with express passport, I came across the following: decl ...

Setting up "connect-redis" in a TypeScript environment is a straightforward process

Currently, I am diving into the Fullstack React GraphQL TypeScript Tutorial I encountered an issue while trying to connect Redis with express-session... import connectRedis from "connect-redis"; import session from "express-session"; ...

Error 414: The URL exceeds the maximum length and cannot be processed

I am currently utilizing vuejs and sending an axios request to the server in order to download a csv file. download() { var that = this //this.records = [{id: 1, name: 'Jack'}, {id: 2, name: 'Jacky'}, {id: 3, name: &apos ...

How can I add scrolling functionality to the active list item with React?

I created a music player that allows users to search for songs by artist. Check out the CODE SANDBOX here! Take a look at how the SongsList component is structured in my project: const SongsList = (props) => { const { loading, errorMess ...

Issue encountered when attempting to assign an action() to each individual component

I'm facing an issue with the button component I've created. import { Component, OnInit, Input } from '@angular/core'; @Component({ selector: 'app-button', template: ` <ion-button color="{{color}}" (click)="action()"&g ...