如何使用Typescript扩展Material-UI组件的道具?

时间:2017-09-11 09:51:55

标签: reactjs typescript material-ui

我想使用typescript从Material-UI扩展Button组件的道具,以便能够将额外的道具传递给它的孩子们。

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>

我尝试在./app/types/material_ui.d.ts中添加以下声明:

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

抛出错误“TS2693:'Button'只引用一个类型,但在这里被用作值。”。

我也试过了声明:

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> { }
}

抛出错误“TS2323:无法重新声明导出的变量'按钮'”。

我的tsconfig.json看起来像这样:

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

最后来自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> {}

我正在使用material-ui 1.0.0-beta.8 with react 15.6.1,react-router-dom 4.2.2和typescript 2.5.2。

4 个答案:

答案 0 :(得分:1)

以下代码适用于我

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> {
  }

}

我没有"TS2693: 'Button' only refers to a type, but is being used as a value here.的问题,我也使用Typescript 2.5.2

答案 1 :(得分:0)

这里是扩展Material UI Button(未经测试)的简约示例。 扩展字段将简单地附加在按钮标签之后。

import * as React from 'react';
import { ButtonProps } from '@material-ui/core/Button';
import { Button } from '@material-ui/core';

interface Props{
  extendedField: string;
}

export class MyExtendedButton extends React.Component<ButtonProps & Props>{
  render(){

    const {
      extendedField,
      children,
      ...buttonProps,
    } = this.props;

    return (<Button {...buttonProps}>
      {children}
      : <span style={{color: 'red'}}>
        {extendedField}
      </span>
    </Button>);
  }
}

答案 2 :(得分:0)

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;

答案 3 :(得分:0)

有点晚了,但这是另一种解决方案。另请参阅 MUI 文档 Usage of component prop 。 以下按钮使用链接组件。它也使用 Link 的特定道具及其类型。它还添加了自己的重要道具。

import React from 'react'
import MuiButton, {ButtonProps} from '@material-ui/core/Button'

interface ButtonOptions {
    // your custom options with their types
  }

const Button = <C extends React.ElementType>(props: ButtonProps<C, {component?: C}> & ButtonOptions ) => {
  return <MuiButton {...props}>{props.children}</MuiButton>
}

export default Button
 
// use like this:  
import {Link} from 'react-router-dom'
<Button component={Link} to={'/somelocation'}>