How do I fix "[ts] Property 'getAttribute' does not exist on type 'EventTarget'"

Viewed 3745

I am trying to create an onClick event type to capture the target attribute in React while using TypeScript. But I am getting the error "[ts] Property 'getAttribute' does not exist on type 'EventTarget'." Can anyone help provide insight into best practice on how to fix this?

I tried to use another helper function for the event.target part. That way I can typeset this part, and the getAttribute part in this function. However, I was told this is not best practice and wrong approach.

const Option = (props: OptionProps) => {

  const HandleOptionChange = (event: React.MouseEvent<HTMLLIElement>) => {
    return props.onOptionChange(event.target.getAttribute('value'));
  }

  return (
    <li
      key={props.key}
      value={JSON.stringify(props.word)}
      onClick={HandleOptionChange}
    >
      {props.word.value}
    </li>
  )
}

ts error message:

[ts] Property 'getAttribute' does not exist on type 'EventTarget'. any

3 Answers

this works for me

const HandleOptionChange = (event: React.MouseEvent<HTMLLIElement>) => {
    const el = event.target as HTMLInputElement
    return props.onOptionChange(el.getAttribute('value'));
  }

i've just added HTMLInputElement as event.target type

Old question, but in case anyone else comes across it, here's an answer:

You should be using event.currentTarget instead of event.target

event.currentTarget points to the element on which you've attached the listener. In this case, it is the HTMLLIElement, as specified by React.MouseEvent<HTMLLIElement>

event.target on the other hand, is the element that originated the event, which may not be the one the listener is attached to! Any of the children of <li> could start a mouse event if they're clicked. Since the type of element is unknown, as it could literally be anything(<p> or <img> or <div> or anything else), typescript cannot confirm that any of the values/methods exist on it.

consider this:

return (
  <li
    key={props.key}
    value={JSON.stringify(props.word)}
    onClick={HandleOptionChange}
  >
    content of the li
    <div>
      header title for the image
      <img src="https://example.image.source/" />
    </div>
  </li>
)

You could click on the image and event.target would be the <img> element, which does not have a value attribute, which would make your code throw an error. Same thing would happen if you clicked on "header title for the image", the event.target would be the <div> element.

Using event.currentTarget will always return the <li> element that the listener is attached to in all those scenarios. Your code will then behave as you would expect it to in all of those instead of throwing errors.

As an aside, for anyone looking at this question for other similar circumstances: Davit's answer is addressing the symptom without addressing the cause, and could hide away bugs from your linter in your own codebase. Make sure you understand why you're getting an error so you can fix it instead of just hiding it.

Was facing the same issue and I solved it by explicitly telling TS what type the currentTarget will be:

const handleToggle = (event: { currentTarget: HTMLButtonElement | null }) => 
  {
    const state = event.currentTarget?.getAttribute('aria-checked');
    // do some crazy stuff
  };
Related