带有TypeScript的MUIv4升级-无法正确地将道具传播到TextField

时间:2019-06-12 16:11:23

标签: reactjs typescript material-ui mui

当前Material-UI版本:4.1.0

我在将道具传播到我创建的抽象<TextField />组件时遇到问题。

代码如下:

PasswordInput.tsx

import * as React from 'react'
import TextField, { Props as TextFieldProps } from 'src/TextField'

type Props = TextFieldProps & {
  hideHelperText?: boolean;
};

class PasswordInput extends React.Component<Props> {
  onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    /** do stuff */
  };

  render() {
    const {
      hideHelperText,
      classes,
      ...rest
    } = this.props;

    return (
      <React.Fragment>
        <TextField
          /** errors out here */
          /*
            Type 'HideShowText | null' is not assignable to type 'HTMLDivElement | null'.
            Type 'HideShowText' is missing the following properties from type 'HTMLDivElement':
            align, addEventListener, removeEventListener, accessKey, and 238 more
          */
          {...rest}
          onChange={this.onChange}
        />
        {!hideHelperText && 'hello world'}
      </React.Fragment>
    );
  }
}

export default PasswordInput;

TextField.tsx

import TextField, {
  StandardTextFieldProps as TextFieldProps
} from '@material-ui/core/TextField';

type ClassNames =
  | 'root'

const styles = (theme: Theme) =>
  createStyles({
    root: {},
  });

interface BaseProps {
  tooltipText?: string;
  dataAttrs?: Record<string, any>
}

export type Props = BaseProps & TextFieldProps

type CombinedProps = Props &
  WithStyles<ClassNames>;

class MyTextField extends React.Component<CombinedProps> {
  render() {
    const {
      children,
      tooltipText,
      dataAttrs,
      /** everything else that goes on the root */
      ...textFieldProps
    } = this.props;

    return (
      <div
      >
        <TextField
          {...textFieldProps}
          {...dataAttrs}
        >
          {this.props.children}
        </TextField>
        {tooltipText && <HelpIcon text={tooltipText} />}
      </div>
    );
  }
}

const styled = withStyles(styles);

export default compose<CombinedProps, Props>(
  styled
)(MyTextField);

正在轰炸,并显示以下错误:

TS2322: Type '{ tooltipText: string | undefined; value: string | undefined; onChange: (e: ChangeEvent<HTMLInputElement>) => void; fullWidth: true; required: boolean | undefined; errorText?: string | undefined; ... 282 more ...; innerRef?: ((instance: any) => void) | ... 2 more ... | undefined; }' is not assignable to type 'IntrinsicClassAttributes<HideShowText>'.
  Types of property 'ref' are incompatible.
    Type '((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null | undefined' is not assignable to type 'string | ((instance: HideShowText | null) => void) | RefObject<HideShowText> | null | undefined'.
      Type '(instance: HTMLDivElement | null) => void' is not assignable to type 'string | ((instance: HideShowText | null) => void) | RefObject<HideShowText> | null | undefined'.
        Type '(instance: HTMLDivElement | null) => void' is not assignable to type '(instance: HideShowText | null) => void'.
          Types of parameters 'instance' and 'instance' are incompatible.
            Type 'PasswordInput | null' is not assignable to type 'HTMLDivElement | null'.
              Type 'PasswordInput' is missing the following properties from type 'HTMLDivElement': align, addEventListener, removeEventListener, accessKey, and 238 more.

PasswordInput中的...rest应该等于StandardTextFieldProps,但是由于某些原因,我的组件不是HTMLDivElement时出现错误?

让我知道是否可以提供更多细节。据我所知,这是一个错误。

2 个答案:

答案 0 :(得分:0)

昨天我遇到了这个确切的错误。我在其他地方(例如使用SelectProps)进行相同类型的联合,没有问题,但是TextFieldProps在多个属性上有问题,而StandardTextFieldProps仅在ref上存在问题。因此,作为临时措施,您可以声明:

export type MyTextFieldProps = Omit< StandardTextFieldProps, 'ref' > & { ... }

答案 1 :(得分:0)

@flatline。谢谢你的建议。在更改导出的键入方式时,我也有一个可行的解决方案。老实说,我不确定这为什么行得通,但确实行得通。注意每个文件中的最后几行:

TextField.tsx
import TextField, {
  StandardTextFieldProps as TextFieldProps
} from '@material-ui/core/TextField';

type ClassNames =
  | 'root'

const styles = (theme: Theme) =>
  createStyles({
    root: {},
  });

interface BaseProps {
  tooltipText?: string;
  dataAttrs?: Record<string, any>
}

export type Props = BaseProps & TextFieldProps

type CombinedProps = Props &
  WithStyles<ClassNames>;

class MyTextField extends React.Component<CombinedProps> {
  render() {
    const {
      children,
      tooltipText,
      dataAttrs,
      /** everything else that goes on the root */
      ...textFieldProps
    } = this.props;

    return (
      <div
      >
        <TextField
          {...textFieldProps}
          {...dataAttrs}
        >
          {this.props.children}
        </TextField>
        {tooltipText && <HelpIcon text={tooltipText} />}
      </div>
    );
  }
}

const styled = withStyles(styles);

export default compose<CombinedProps, Props>(
  styled
)(MyTextField) as s React.ComponentType<Props>;;
PasswordInput.tsx
import * as React from 'react'
import TextField, { Props as TextFieldProps } from 'src/TextField'

type Props = TextFieldProps & {
  hideHelperText?: boolean;
};

class PasswordInput extends React.Component<Props> {
  onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    /** do stuff */
  };

  render() {
    const {
      hideHelperText,
      classes,
      ...rest
    } = this.props;

    return (
      <React.Fragment>
        <TextField
          /** errors out here */
          /*
            Type 'HideShowText | null' is not assignable to type 'HTMLDivElement | null'.
            Type 'HideShowText' is missing the following properties from type 'HTMLDivElement':
            align, addEventListener, removeEventListener, accessKey, and 238 more
          */
          {...rest}
          onChange={this.onChange}
        />
        {!hideHelperText && 'hello world'}
      </React.Fragment>
    );
  }
}

export default PasswordInput as React.ComponentType<Props>;;