3

TL;DR Object.getPrototypeOf(e.target) returns HTMLInputElement but the compiler says that the type is EventTarget

Long: I have a simple input

      <input
        className="FilterInput"
        type="text"
        placeholder="Search for names..."
        onKeyUp={filter}
      />

and a function to manage the filter

    const filter = (e: React.KeyboardEvent<HTMLInputElement>) => {
        console.log(Object.getPrototypeOf(e.target)) // prints "HTMLInputElement"
        console.log((e.target as HTMLInputElement).value);
        // ... other code
    }

I'm trying to understand better the theory that is behind the type management of Typescript, however I don't understand why I have to typehint

(e.target as HTMLInputElement).value

in the second console.log.

If I don't do it, the compiler (compile time) says Property 'value' does not exist on type 'EventTarget'.. So this means that at compile time the type of e.target is EventTarget.

However, at runtime tested with Object.getPrototypeOf(e.target), the type is HTMLInputElement (which has the value property).

Why is this happening? Is it an error in my code, something related to React or some part of the theory of the type management in Typescript that I'm missing?

Moreover, shouldn't the indication of the generic type in the parameter declaration (e: React.KeyboardEvent<HTMLInputElement>) be enough?

Thanks

LombaX
  • 17,265
  • 5
  • 52
  • 77
  • this is odd. i copied your filter method into my IDE and it did not complain after i removed your assertion (which i would consider intended, because of the reasons you describe). `e.target.value` throws no compile time error. – Dean Jul 12 '22 at 15:39

1 Answers1

5

The answer to this is actually more related to JS and DOM api's then it is to Typescript.

In short, what you really want is event.currentTarget, as it will be the actual element to which you attached the listener.

event.target can be any child element of your element. As it can be any element - it can't be typed safety, so it's typed as the lowest common denominator which is EventTarget. (but I will say I'm not sure why it's EventTarget and not Element)

For more information see this answer: What is the exact difference between currentTarget property and target property in JavaScript

Aviad Hadad
  • 1,717
  • 12
  • 15