Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Property 'value' does not exist on 'EventTarget' in TypeScript

The following code in TypeScript with React is outputting the following error.

Property 'value' does not exist on type 'EventTarget'.

import React, { Component } from 'react';

class InputForm extends React.Component<any ,any> {
  state = {
    userInput: ''
  };

  handleUserInput = (e: React.FormEvent<HTMLInputElement>): void => {
    this.setState({
      userInput: e.target.value
    });
  }

  // Working code from 42081549
  // Not relevant to this project
  update = (e: React.FormEvent<HTMLInputElement>): void => {
    this.props.login[e.currentTarget.name] = e.currentTarget.value
  }

  submitMessage = (e: React.FormEvent<HTMLFormElement>): void => {
    e.preventDefault();
    this.props.sendUserMessage(this.state.userInput)
  }

  render() {
    return (
      <form className="chat-input-form" onSubmit={this.submitMessage}>
        <input value={this.state.userInput} onChange={this.handleUserInput}/>
        <button type="submit" />
      </form>
    );
  }

}

export default InputForm;

I am currently using:

  • "@types/react": "^16.0.40",

  • "react": "^16.2.0",

  • "typescript": "^2.7.2",

This could be considered a follow-up to Typescript: React event types however it is not a duplicate as working code provided in by Nitzan Tomer in this answer is currently not working in my specific use case.

EDIT As mentioned above, NOT a duplicate of Typescript: React event types, the solution provided in that question is not working in this case, and therefore could be a different cause.

My tsconfig.json file is as follows:

{
  "compilerOptions": {
    "target": "es5",                          
    "module": "commonjs", 
    "lib": ["esnext", "dom"],
    "jsx": "react",                           
    "sourceMap": true,                        
    "outDir": "./dist/",                      
    "strict": true,                        
    "noImplicitAny": true,                   
    "esModuleInterop": true                 
  }
}
like image 432
tomhughes Avatar asked Mar 07 '18 12:03

tomhughes


2 Answers

The problem is that you're using e.target.value instead of e.currentTarget.value.

As you can see in the definition file:

interface SyntheticEvent<T> {
    ...
    currentTarget: EventTarget & T;
    ...
    target: EventTarget;
    ...
}
like image 180
Nitzan Tomer Avatar answered Oct 19 '22 22:10

Nitzan Tomer


To elaborate a bit on Nitzan Tomer's answer...

You used to be able to use e.target.value in this way where target would be generic, in this case: HTMLInputElement. The code was reverted to make e.currentTarget generic and make e.target not generic (hard-coded to EventTarget). EventTarget doesn't have a value attribute.

The reason lies in the difference between currentTarget and target. When you refer to target, you refer to the element which triggered the event. If you have a button, with some icon in it. If the icon is directly clicked, then it would be the target. At compile time, you cannot know what element type will trigger the click, but you can know which element the eventListener is registered on. Thus currentTarget is generic.

Further, target is rarely what you want. You typically want the element, where you attached the eventListener.

The Github comment providing the above rationale.
The Github PR where target was made /not/ generic.

like image 29
cdosborn Avatar answered Oct 19 '22 22:10

cdosborn