8

I am trying to use onInput on a generic Input component I've created, everytime I add a DOM event I have a little fight with TypeScript.

This is my component, Input.tsx:

import React, { ChangeEvent, FormEvent } from 'react'

import { InputStyled } from './Input-style'

type InputProps = {
  name: string
  value: string | number
  type?: string
  placeholder?: string
  onInput?: (e: FormEvent<HTMLInputElement>) => void
  onChange?: (e: ChangeEvent<HTMLInputElement>) => void
}

export const Input = (props: InputProps) => (
  <InputStyled
    type={props.type ? props.type : 'text'}
    name={props.name}
    id={props.name}
    placeholder={props.placeholder}
    value={props.value}
    onInput={props.onInput}
    onChange={props.onChange}
   />
)

The problem I am having is that when using the onInput event, it says Property 'value' does not exist on type 'EventTarget'

import React from 'react'
import { Input } from '@components'

export const Main = () => {
  const [rate, setRate] = useState<number>(0)

  return (
    <Input
      type='number'
      name='Rate'
      value={rate}
      placeholder='Decimal number'
      onInput={e => setRate(Number(e.target.value))}
    />
  )
}
2
  • I think onInput isn't used that much, and is apparently the same as onChange for react (see stackoverflow.com/questions/38256332/…). The target property of the parameter passed to the onChange handler has a value that you can use. Commented Feb 1, 2022 at 10:26
  • I was recommended onInput because it had support for drag and drop, cut and paste, up/down arrows on a number field. In any case can you not use onInput with TypeScript for value? Commented Feb 1, 2022 at 10:28

3 Answers 3

19

Explicitly typing the parameter of the handler works:

<Input
  onInput={(event: React.ChangeEvent<HTMLInputElement>) => setRate(event.target.value) }
/>
Sign up to request clarification or add additional context in comments.

Comments

0

target can be an eventTarget interface, so you need to check what the target is

<input onInput={({target}) => {
  if (target instanceof HTMLInputElement) {
    onInput(target.value)
  }
}}/>

Comments

-3

Do this:

onInput = (event: Event) => {
      const { value } = event.target as unknown as { value: number };
      setRate(value);
};
  
<Input onInput={onInput} />

and the squeegee lines will go away.

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.