4

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))}
    />
  )
}
Álvaro
  • 2,255
  • 1
  • 22
  • 48
  • I think `onInput` isn't used that much, and is apparently the same as `onChange` for react (see https://stackoverflow.com/questions/38256332/in-react-whats-the-difference-between-onchange-and-oninput). The `target` property of the parameter passed to the `onChange` handler has a `value` that you can use. – colinD Feb 01 '22 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? – Álvaro Feb 01 '22 at 10:28

2 Answers2

10

Explicitly typing the parameter of the handler works:

<Input
  onInput={(event: React.ChangeEvent<HTMLInputElement>) => setRate(event.target.value) }
/>
colinD
  • 1,641
  • 1
  • 20
  • 22
0

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.

LEMUEL ADANE
  • 8,336
  • 16
  • 58
  • 72