Current Material-UI Version: 4.1.0
I am having issues spreading props to an abstracted <TextField />
component I've created.
Here is the code:
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);
It's bombing with the following error:
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.
It appears that the ...rest
in the PasswordInput should be equal to the StandardTextFieldProps
but for some reason I'm getting errors for my component not being an HTMLDivElement
?
Let me know if I can provide more detail. As far as I can tell, this is a bug.
I ran into this exact error yesterday. I'm doing the same type union in other places, such as with SelectProps
, without an issue, but TextFieldProps
is problematic on multiple properties and StandardTextFieldProps
on just ref
. Therefore, as a temporary measure you could declare:
export type MyTextFieldProps = Omit< StandardTextFieldProps, 'ref' > & { ... }