Property 'value' does not exist on type EventTarget in TypeScript [duplicate]
Asked Answered
E

18

341

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.

Experimental answered 2/6, 2017 at 5:20 Comment(4)
we can use (e.target as HTMLInputElement).valueBergquist
Bro, I struggled with this for hours, you simply have to remove the type from the method. onUpdatingServerName(event);Lycaon
@Lycaon esLint will automatically add it back or complain and refuse to compile. Can't change this rule for a project with multiple developers.Strongbox
@RinandLen You could maybe try using the any typeLycaon
P
485

event.target here is an HTMLElement which is the parent of all HTML elements, but isn't guaranteed to have the property value. TypeScript detects this and throws the error. Cast event.target to the appropriate HTML element to ensure it is HTMLInputElement which does have a value property:

(event.target as HTMLInputElement).value

Per the documentation:

Type the $event

The example above casts the $event as an any type. That simplifies the code at a cost. There is no type information that could reveal properties of the event object and prevent silly mistakes.

[...]

The $event is now a specific KeyboardEvent. Not all elements have a value property so it casts target to an input element.

(Emphasis mine)

Poleax answered 2/6, 2017 at 5:26 Comment(5)
A bit cleaner syntax var element = ev.target as HTMLElementParotid
For me, HTMLInputElement worked instead of HTMLElement as HTMLElement does not have value in the interface.Amelita
The best approach, in my opinion, is having onFieldUpdate(event: { target: HTMLInputElement }) { in the called function. See my answer below.Tailstock
For Angular 9 use "as" syntax. event.target as HtmlInputlementUnsay
@Unsay @Alessandro_russo - Safer would be: event.target instanceof HTMLInputElement ? event.target.value : undefinedAforementioned
A
188

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;
}
Amadeus answered 8/6, 2018 at 15:51 Comment(4)
This will not work if the function is called from i.e. an onChange proeperty handler reference in React code though. The react handler does not expect the type to be set for the React.ChangeEvent and will show a typing error. I had to revert to (a variant of) the selected answer instead, with a cast: (event.target as HTMLInputElement).value.Belligerency
This seemed to work for me fine in a React component. Maybe it's the version of React? We're currently on 16.8.*.Massasauga
Note that your answer is only relevant to react. The OP was asking about angular.Salop
I like this approach better than the casting , but it's true that sometimes we use onBlur or onKeyDown , things like thaCivility
S
92

Here's another fix that works for me:

(event.target as HTMLInputElement).value

That should get rid of the error by letting TS know that event.target is an HTMLInputElement, which inherently has a value. Before specifying, TS likely only knew that event alone was an HTMLInputElement, thus according to TS the keyed-in target was some randomly mapped value that could be anything.

Soper answered 4/1, 2018 at 17:34 Comment(1)
This was really helpful in React where it tried to interpret <HTMLInputElement> as JSX.Premeditate
M
37

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…
}
Majors answered 10/2, 2019 at 22:5 Comment(3)
Question is tagged as Angular so a React answer seems off topic.Nieman
Regardless… it has multiple up votes, thus this answer has been helpful to others.Majors
Works like a charm. onChange={(event: ChangeEvent<HTMLInputElement>): void => { setTextFilter(event.target.value); }}Lubricator
L
29

In template -

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

in component -

getInput(event: Event) {
  this.value1 = (event.target as HTMLInputElement).value;
}
Lemos answered 25/8, 2021 at 13:26 Comment(0)
T
24

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.

Tailstock answered 28/5, 2020 at 17:5 Comment(1)
This should be up there with the best answer thanks :)Dematerialize
D
15

This works for me in ANGULAR HTML Component !!

$any($event.target).value

Source Link: https://www.tektutorialshub.com/angular/property-value-does-not-exist-on-type-eventtarget-error-in-angular/

Dustin answered 15/2, 2022 at 19:8 Comment(1)
This works for me in Angular 16. <3Unduly
C
8

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

Read more here.

Cetus answered 12/5, 2022 at 10:37 Comment(0)
J
7

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" 
/>
Jonijonie answered 28/5, 2022 at 11:47 Comment(0)
M
3

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

Mcbride answered 8/10, 2019 at 2:20 Comment(0)
I
2

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;
}
Indrawn answered 8/5, 2022 at 9:33 Comment(0)
G
2

Please try this one

<input type = 'text' [value] = 'value' (input) = 'data = $any($event.target).value'>
Gastroenteritis answered 21/6, 2022 at 19:8 Comment(0)
Y
1

you can also create your own interface as well.

    export interface UserEvent {
      target: HTMLInputElement;
    }

       ...

    onUpdatingServerName(event: UserEvent) {
      .....
    }
Yolanthe answered 26/8, 2020 at 21:4 Comment(0)
F
1

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

onUpdatingServerName(event: Event) {
  console.log(event);
  this.newserverName = (<HTMLInputElement>event.target).value; 
}
Feminism answered 30/6, 2021 at 1:21 Comment(0)
Y
0

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;
}
Yost answered 4/8, 2021 at 11:30 Comment(0)
S
0

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);
}
Suprasegmental answered 5/11, 2021 at 22:10 Comment(0)
S
-7

Try code below:

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

it works for me :-)

Stent answered 6/1, 2021 at 16:24 Comment(1)
better remove your answerShrunken
P
-15

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]

Psychomancy answered 17/8, 2020 at 14:13 Comment(4)
Welcome on the SO! Why and how? Please explain.Spry
you may remove your answer if it get minused hardlyShrunken
By adding any will give warning on compile-time, and not recommended to use any in TS file, otherwise the purpose of using ts file is dying.Constantan
@ZeeshanSafdar I agree that you shouldn't do what @Psychomancy has done here, however any is perfectly fine to use in cases where the object can in fact be anything. In general, if you know what the object's properties are (like we do here), you shouldn't be using any. If the object can have any properties, you should use any.Countershaft

© 2022 - 2024 — McMap. All rights reserved.