wyc
wyc

Reputation: 55283

Property 'nodeName' does not exist on type 'EventTarget'

The following code is checking whether the user is in an input, textarea, or contenteditable. If that's the case keys should be emptied and the code should stop.

let keys: any[] = []

document.addEventListener('keypress', event => {
  if (event.key === ' ') return
  if (event.target === null) return // Should remove this?
  if (event.target.nodeName === 'INPUT' ||
    event.target.nodeName === 'TEXTAREA' ||
    event.target.isContentEditable) {
    keys = []
    return
  }
})

console.log(keys)

I'm getting this TypeScript error:

Property 'nodeName' does not exist on type 'EventTarget'.
Property 'nodeName' does not exist on type 'EventTarget'.
Property 'isContentEditable' does not exist on type 'EventTarget'.

Why is this and how to fix it?

Live code: https://codesandbox.io/s/cover-image-forked-7n8z7w?file=/src/index.ts

Upvotes: 6

Views: 1802

Answers (2)

Jared Smith
Jared Smith

Reputation: 21926

Event targets can include things like xhr requests and web workers, so Typescript correctly won't let you assume it's a DOM node.

Once you realize that, it just becomes a matter of narrowing the type via runtime checks that are legible to the compiler.

document.addEventListener('keypress', (evt: KeyboardEvent) => {
  const { target } = evt;
  // Note e.g. XHR requests can be event targets, no nodeName
  if (target instanceof HTMLElement) {
    console.log(target.nodeName);
    if (target.isContentEditable) {
      // now we're good to process as e.g. textarea
    }
  }
});

Playground

Upvotes: 6

geoffrey
geoffrey

Reputation: 2444

EventTarget is not guarantied to be an HTMLElement or even a Node

You may replace your second condition with

if (!(event.target instanceof HTMLElement)) return;

Upvotes: 13

Related Questions