victor zadorozhnyy
victor zadorozhnyy

Reputation: 969

What type should I use for input react-bootstrap event with TypeScript?

I'm using react-bootstrap lib and need to use an input component. I know how to type a simple input but have a problem with FormControl

class Search extends Component<Props, { searchInput: string }> {

      static defaultProps = {}

      state = {
        searchInput: ""
      }

     // This one works for input 
      searchInputSimple = (e: React.FormEvent<HTMLInputElement>): void => {
        const { getSearch } = this.props
        this.setState(
          { searchInput: e.currentTarget.value },
          (): void => getSearch(this.state.searchInput)
        )
      }

      // for FormControl. What can I use exept any?
      searchInput = (e: React.FormEvent<any>): void => {
        const { getSearch } = this.props
        this.setState(
          { searchInput: e.currentTarget.value },
          (): void => getSearch(this.state.searchInput)
        )
      }

      render() {
        const { searchInput } = this.state
        return (
          <>
            <InputGroup className="mb-3">
              <FormControl placeholder="Search" value={searchInput} onChange={this.searchInput} />
            </InputGroup>

            <input
              placeholder="Search"
              value={searchInput}
              onChange={this.searchInputSimple}
              className="form-control"
            />
          </>
        )
      }
    }

I tried to understand and look at FormControl.d.ts

import Feedback from './Feedback';

import { BsPrefixComponent } from './helpers';

interface FormControlProps {
  innerRef?: React.LegacyRef<this>;
  size?: 'sm' | 'lg';
  plaintext?: boolean;
  readOnly?: boolean;
  disabled?: boolean;
  value?: string;
  onChange?: React.FormEventHandler<this>;
  type?: string;
  id?: string;
  isValid?: boolean;
  isInvalid?: boolean;
}

declare class Form<
  As extends React.ReactType = 'input'
> extends BsPrefixComponent<As, FormControlProps> {
  static Feedback: typeof Feedback;
}

If I use just HTMLInputElement I'm getting this error

Type error: Type '(e: FormEvent) => void' is not assignable to type '(event: FormEvent & FormControlProps>>) => void'. Types of parameters 'e' and 'event' are incompatible. Type 'FormEvent & FormControlProps>>' is not assignable to type 'FormEvent'. Type 'Pick, HTMLInputElement>, "children" | "form" | "style" | "title" | "pattern" | "ref" | "key" | "defaultChecked" | ... 268 more ... | "width"> & BsPrefixProps<...> & FormControlProps' is missing the following properties from type 'HTMLInputElement': align, autocomplete, autofocus, dirName, and 245 more.

So how to do it and not to use any type? Should it be an alias HTMLInputElement and something more?

Upvotes: 11

Views: 8859

Answers (5)

allen sparks
allen sparks

Reputation: 1

React bootstraps declares this type in FormControl without exporting it. It is simply made up of a union of 3 types

declare type FormControlElement = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;

What you need is:

event: React.ChangeEvent<
      HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
    >,

If this definition ever changes, go look up the docs and update with the types that exist.

Upvotes: 0

Noumenon
Noumenon

Reputation: 6412

None of the other answers worked for me, but typing as React.BaseSyntheticEvent as suggested here did.

Upvotes: 0

Wings
Wings

Reputation: 582

If you are using React.ChangeEvent this way

(e: React.ChangeEvent<HTMLInputElement>)

Please note that in your HTML code you should NOT call your function like this:

onChange={(e) => searchInput(e)}

Instead call it this way:

onChange={searchInput}

Upvotes: 4

Yejia Chen
Yejia Chen

Reputation: 21

Instead of any, use FormControl & FormControlProps.

searchInput = (e: React.FormEvent<FormControl & FormControlProps>): void => {
  const { getSearch } = this.props
  this.setState(
    { searchInput: e.currentTarget.value as string},
    (): void => getSearch(this.state.searchInput)
  )
}

Taken from this comment on the issue in @types/react-bootstrap.

Upvotes: 2

tombraider
tombraider

Reputation: 1167

You're looking for a React.ChangeEvent, rather than a React.FormEvent:

searchInput = (e: React.ChangeEvent<HTMLInputElement>): void => {
    const { value } = e.currentTarget;
    const { getSearch } = this.props;
    this.setState(state => ({
        ...state,
        searchInput: value
    }), (): void => getSearch(this.state.searchInput))
}

Upvotes: 8

Related Questions