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

Viewed 264740

So the following code is in Angular 4 and I can't figure out why it doesn't work the way as expected.

Here is a snippet of my handler:

onUpdatingServerName(event: Event) {
  console.log(event);
  this.newserverName = event.target.value; //this wont work
}

HTML element:

<input type="text" class="form-control" (input)="onUpdatingServerName($event)">

The code gives me the error:

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

But as it can be seen in the console.log that value does exist on the event.target.

18 Answers

Passing HTMLInputElement as a generic to the event type should work too:

onUpdatingServerName(event: React.ChangeEvent<HTMLInputElement>) {
  console.log(event);
  this.newserverName = event.target.value;
}

I was looking for a solution to a similar TypeScript error with React:

Property 'dataset' does not exist on type EventTarget in TypeScript

I wanted to get to event.target.dataset of a clicked button element in React:

<button
  onClick={onClickHandler}
  data-index="4"
  data-name="Foo Bar"
>
  Delete Candidate
</button>

Here is how I was able to get the dataset value to "exist" via TypeScript:

const onClickHandler = (event: React.MouseEvent<HTMLButtonElement>) => {
  const { name, index } = (event.target as HTMLButtonElement).dataset
  console.log({ name, index })
  // do stuff with name and index…
}

In template -

`(keyup)="value2=$any($event.target).value"`

in component -

getInput(event: Event) {
  this.value1 = (event.target as HTMLInputElement).value;
}

The way I do it is the following (better than type assertion imho):

onFieldUpdate(event: { target: HTMLInputElement }) {
  this.$emit('onFieldUpdate', event.target.value);
}

This assumes you are only interested in the target property, which is the most common case. If you need to access the other properties of event, a more comprehensive solution involves using the & type intersection operator:

event: Event & { target: HTMLInputElement }

This is a Vue.js version but the concept applies to all frameworks. Obviously you can go more specific and instead of using a general HTMLInputElement you can use e.g. HTMLTextAreaElement for textareas.

You should use event.target.value prop with onChange handler if not you could see :

index.js:1437 Warning: Failed prop type: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.

Or If you want to use other handler than onChange, use event.currentTarget.value

To solve this problem, use the $any typecast function ($any($event.target).value) to stop the type checking in the template.

Read more here.

React has some interface like ChangeEvent for onChange, FormEvent for onSubmit etc

I was also trying to do similar like this below solution worked for me

handleChange (e : React.ChangeEvent<HTMLInputElement>) {
  console.log(e.currentTarget.value);
}


<input 
   autoFocus
   value={this.state.account.username}
   onChange={this.handleChange}
   id="username" 
   type="text" 
   className="form-control" 
/>

you can also create your own interface as well.

    export interface UserEvent {
      target: HTMLInputElement;
    }

       ...

    onUpdatingServerName(event: UserEvent) {
      .....
    }

Please try this one

<input type = 'text' [value] = 'value' (input) = 'data = $any($event.target).value'>

You can explicitly parse it into "HTMLInputElement" and then access 'value'

onUpdatingServerName(event: Event) {
  console.log(event);
  this.newserverName = (<HTMLInputElement>event.target).value; 
}

As you know, TypeScript has been always strictly on the element data type. So, You can't directly access attributes of an element without specifying its data type. The event.target is an HTMLElement which is the parent of all HTML elements, but isn't guaranteed to have the property value.

So, we need to typecast the variable event.target then only we can access the value attribute from it.

OnUpdatingServerName (event: Event) {
  console.log(event);
  var element = event.target as HTMLElement
  this.newserverName = element.value;
}

I would recommend creating a utility type:

interface MyEvent<T extends EventTarget> extends Omit<Event, 'target'> {
  target: T;
}

And then use it like this:

function onChange({ target: { value } }: MyEvent<HTMLInputElement>) => {
  doSomethingWith(value);
}

Declare interface

export interface HTMLInputEvent extends Event {
  target: HTMLInputElement & EventTarget;
}

which can be re-used as a type for different input events

public onChange(event: HTMLInputEvent) {
  const value = event.target.value;
}

Try code below:

  console.log(event['target'].value)

it works for me :-)

add any type to event

event: any

example

[element].addEvenListener('mousemove', (event: any) =>{
//CODE//
} )

what happens is that typescript adds "event" (click in this case) as Event type and for some reason it doesn't recognize some properties. Adding it of type any no longer exists this problem, this works for any document.[Property]

Related