LombaX
LombaX

Reputation: 17364

Typescript and React, different Types between Compile Time and Runtime for React.KeyboardEvent<HTMLInputElement>

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

Upvotes: 3

Views: 350

Answers (1)

Aviad Hadad
Aviad Hadad

Reputation: 1717

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

Upvotes: 5

Related Questions