3

I'm writing a React application using TypeScript. I use material-ui for my components. I'm currently writing a wrapper for material-ui's input like this:

import FormControl, { FormControlProps } from "@material-ui/core/FormControl";
import MUIInput, { InputProps } from "@material-ui/core/Input";
import InputLabel, { InputLabelProps } from "@material-ui/core/InputLabel";
import withStyles, { WithStyles } from "@material-ui/core/styles/withStyles";
import classNames from "classnames";
import React, { PureComponent, ReactNode } from "react";
import styles from "./styles";

export interface OwnProps {
  labelText?: ReactNode;
  labelProps?: InputLabelProps;
  id?: string;
  inputProps?: InputProps;
  formControlProps?: FormControlProps;
  inputRootCustomClasses?: string;
  success?: boolean;
  white?: boolean;
  error?: boolean;
}

export interface Props extends WithStyles<typeof styles>, OwnProps {}

export class Input extends PureComponent<Props> {
  render() {
    const {
      classes,
      formControlProps,
      labelText,
      id,
      labelProps,
      inputProps,
      error,
      white,
      inputRootCustomClasses,
      success
    } = this.props;
    const labelClasses = classNames({
      [" " + classes.labelRootError]: error,
      [" " + classes.labelRootSuccess]: success && !error
    });
    const underlineClasses = classNames({
      [classes.underlineError]: error,
      [classes.underlineSuccess]: success && !error,
      [classes.underline]: true,
      [classes.whiteUnderline]: white
    });
    const marginTop = classNames({
      [inputRootCustomClasses!]: inputRootCustomClasses !== undefined
    });
    const inputClasses = classNames({
      [classes.input]: true,
      [classes.whiteInput]: white
    });
    let formControlClasses;
    if (formControlProps !== undefined) {
      formControlClasses = classNames(formControlProps.className, classes.formControl);
    } else {
      formControlClasses = classes.formControl;
    }
    return (
      <FormControl {...formControlProps} className={formControlClasses}>
        {labelText !== undefined ? (
          <InputLabel
            className={classes.labelRoot + " " + labelClasses}
            htmlFor={id}
            {...labelProps}
          >
            {labelText}
          </InputLabel>
        ) : null}
        <Input
          classes={{
            disabled: classes.disabled,
            input: inputClasses,
            root: marginTop,
            underline: underlineClasses
          }}
          id={id}
          {...inputProps}
        />
      </FormControl>
    );
  }
}

export default withStyles(styles)(Input);

I have a problem with this <Input />'s properties:

classes={{
  disabled: classes.disabled,
  input: inputClasses,
  root: marginTop,
  underline: underlineClasses
}}

For disabled, inputt throws the error:

[ts]
Type 'string | undefined' is not assignable to type 'string'.
  Type 'undefined' is not assignable to type 'string'.

I can't figure out how to solve this. I tried as:

underline: underlineClasses as string

Doesn't work. I tried using the ! operator to assert not-null, but it doesn't work. The weirdest thing about it is that the function classNames always returns a string (even if its empty). Furthermore classes.disabled is also always defined, since its included within my styles.

How can I solve this? I'm developing in strict mode so this linter hickup crashes my application.

2 Answers 2

2

The thing is, a property on a object can be undefined and you input prop in this case needs a string so, a way to fix is:

classes={{
   disabled: classes.disabled,
   input: inputClasses,
   root: marginTop,
   underline: underlineClasses || ''
}}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your help. Unfortunately this doesn't solve the problem. After reading your answer I tried both: classes.disabled || 'false' and classes.disabled || 'undefined'. I also tried passing these as literally false or undefined (not as a string). The errors remain.
Your problem is with the disabled or underline property ?
1

Found my own error 🤦🏻‍♂️ I accidentally wrote <Input /> again instead of <MUIInput />.

<MUIInput
  classes={{
    disabled: classes.disabled,
    input: inputClasses,
    root: marginTop,
    underline: underlineClasses
  }}
  id={id}
  {...inputProps}
/>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.