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

Posted

技术标签:

【中文标题】如何使用 Typescript 扩展 Material-UI 组件的道具?【英文标题】:How to extend props for Material-UI components using Typescript? 【发布时间】:2018-02-19 12:33:16 【问题描述】:

我想使用 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:无法重新声明导出的变量 'Button'”。

我的 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 和 react 15.6.1、react-router-dom 4.2.2 和 typescript 2.5.2。

【问题讨论】:

【参考方案1】:
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;

【讨论】:

谢谢,它有效。有人知道在哪里可以找到和提取 Box 的“justifyContent”属性的默认值吗?【参考方案2】:

以下代码对我有用

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

【讨论】:

看起来很简单,但对我来说这行不通。我收到以下错误:TS2323:无法重新声明导出的变量“Button”。 TS2484:导出声明​​与“Button”的导出声明冲突。这可能与 @987654321 有关@。有什么想法吗? 有趣,这是另一个issue,你能创建一个最小的可重现回购吗? @eitido 我知道已经两年了,但是对于其他来到这里的人来说,原因是 Button 是一个 MUI 组件,而您正在尝试创建自己的 Button 组件,所以这是一个命名冲突.您只需将 MUI 的按钮别名为 MuiButton(或其他名称)。 它只是不起作用。它对其他人有用吗?【参考方案3】:

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

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>);
  

【讨论】:

非常有帮助,感谢分享基于类的示例 :)【参考方案4】:

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

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

【讨论】:

以上是关于如何使用 Typescript 扩展 Material-UI 组件的道具?的主要内容,如果未能解决你的问题,请参考以下文章

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

如何使用 Typescript 在 React 中扩展 HTML 属性

如何使用具有多个页面和入口点的 React 和 TypeScript 设置 chrome 扩展?

带扩展名的 TypeScript 导入

使用 TypeScript 扩展 Express Request 对象

如何扩展 TypeScript 的类型声明?