Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extend props for Material-UI components using Typescript?

I would like to extend the props of the Button component from Material-UI using typescript to be able pass additional props to it's children.

import { NavLink } from 'react-router-dom';
import { Button } from 'material-ui';

<Button
  component={NavLink}

  // NavLink props that needs to be added to typescript declarations
  activeClassName={classes.activeButton}
  exact={true}
  to={to}
>
  {title}
</Button>

I've tried to add the following declarations in ./app/types/material_ui.d.ts:

declare module 'material-ui' {
  interface Button {
    activeClassName?: any;
    exact?: boolean;
    to?: string;
  }
}

Which throws the error "TS2693: 'Button' only refers to a type, but is being used as a value here.".

I've also tried the declaration:

import * as React from 'react';

import { PropTypes, StyledComponent } from 'material-ui';
import { ButtonBaseProps } from 'material-ui/ButtonBase';

declare module 'material-ui' {
  export interface ButtonProps extends ButtonBaseProps {
    color?: PropTypes.Color | 'contrast';
    component?: React.ReactNode;
    dense?: boolean;
    disabled?: boolean;
    disableFocusRipple?: boolean;
    disableRipple?: boolean;
    fab?: boolean;
    href?: string;
    raised?: boolean;
    type?: string;

    activeClassName?: any;
    exact?: boolean;
    to?: string;
  }

  export class Button extends StyledComponent<ButtonProps> { }
}

Which throws the error "TS2323: Cannot redeclare exported variable 'Button'".

My tsconfig.json looks like this:

{
  "compilerOptions": {
    ...
    "paths": {      
      "history": ["./node_modules/@types/history/index"],
      "redux": ["./node_modules/@types/redux/index"],
      "react": ["./node_modules/@types/react/index"],
      "*": ["./app/types/*", "*"]
    },
  },
  ...
}

Finally the original type definition from Material-UI:

import * as React from 'react';
import { StyledComponent, PropTypes } from '..';
import { ButtonBaseProps } from '../ButtonBase';

export interface ButtonProps extends ButtonBaseProps {
  color?: PropTypes.Color | 'contrast';
  component?: React.ReactNode;
  dense?: boolean;
  disabled?: boolean;
  disableFocusRipple?: boolean;
  disableRipple?: boolean;
  fab?: boolean;
  href?: string;
  raised?: boolean;
  type?: string;
}

export default class Button extends StyledComponent<ButtonProps> {}

I am using material-ui 1.0.0-beta.8 with react 15.6.1, react-router-dom 4.2.2 and typescript 2.5.2.

like image 460
eitido Avatar asked Sep 11 '17 09:09

eitido


People also ask

Is material UI compatible with TypeScript?

MUI requires a minimum version of TypeScript 3.5. Have a look at the Create React App with TypeScript example. The strict mode options are the same that are required for every types package published in the @types/ namespace.

How do you modify material UI components?

To customize a specific part of a component, you can use the class name provided by Material UI inside the sx prop. As an example, let's say you want to change the Slider component's thumb from a circle to a square. First, use your browser's dev tools to identify the class for the component slot you want to override.


2 Answers

import React, { FC } from 'react';

import { Button, ButtonProps } from '@material-ui/core';

interface IProps extends ButtonProps {} // your custom props

const ButtonHco: FC<IProps> = ({
  variant,
  color,
  children,
  size,
  disabled
}) => {
  return (
    <Button variant={variant} color={color} size={size} disabled={disabled}>
      {children}
    </Button>
  );
};

export default ButtonHco;
like image 55
Gustavo Mahecha Avatar answered Sep 20 '22 13:09

Gustavo Mahecha


The following code works for me

import { Button, StyledComponent } from 'material-ui';
import { ButtonProps } from 'material-ui/Button';

declare module 'material-ui' {
  export interface MyProps {

    exact?: boolean;
    to?: string;
  }
  export class Button extends StyledComponent<ButtonProps & MyProps> {
  }

}

I don't have the problem with "TS2693: 'Button' only refers to a type, but is being used as a value here. and I'm also using Typescript 2.5.2

like image 22
niba Avatar answered Sep 21 '22 13:09

niba