Question
In an Angular 4 application, an input event handler receives an Event. Why does TypeScript report that Property 'value' does not exist on type 'EventTarget' when accessing event.target.value, even though the browser console shows that the target has a value?
onUpdatingServerName(event: Event) {
console.log(event);
this.newserverName = event.target.value;
}
<input
type="text"
class="form-control"
(input)="onUpdatingServerName($event)"
>
How can the input's value be accessed safely and correctly?
Short Answer
You will learn why TypeScript types event.target broadly as EventTarget | null, why not every event target has a value property, and how to narrow or assert it as an HTMLInputElement before reading its value.
Concept
Browser events can come from many different objects: inputs, buttons, forms, documents, windows, and custom event targets. TypeScript therefore uses the general EventTarget type for event.target.
EventTarget only describes objects that can receive and dispatch events. It does not promise input-specific properties such as value, checked, or files.
Also, event.target can be null, so its full type is commonly:
EventTarget | null
An <input> element is more specific than EventTarget. It is represented by HTMLInputElement, which does have a value: string property. Before using value, tell TypeScript—or prove to TypeScript—that the target is an HTMLInputElement.
The runtime console and TypeScript are answering different questions:
- The console shows the particular object that happened to trigger this event.
Mental Model
Think of EventTarget as a label saying, “this object can receive mail.” An HTMLInputElement is a more specific label saying, “this object can receive mail and has editable text in a value field.”
When TypeScript sees only the general EventTarget label, it cannot assume there is a value field. You must inspect the object or explicitly state that it is an input before opening that field.
Syntax and Examples
Use a type assertion when the handler is only attached to an input element:
onUpdatingServerName(event: Event): void {
const input = event.target as HTMLInputElement;
this.newserverName = input.value;
}
as HTMLInputElement tells TypeScript to treat the target as an input. This is appropriate when your template guarantees that the event comes from this <input>.
For code that may receive events from different sources, use a type guard instead:
onUpdatingServerName(event: Event): void {
const target = event.target;
if (!(target instanceof HTMLInputElement)) {
return;
}
this.newserverName = target.value;
}
After the instanceof HTMLInputElement check, TypeScript narrows target to , so is safe.
Step by Step Execution
Consider this guarded handler:
onUpdatingServerName(event: Event): void {
const target = event.target;
if (!(target instanceof HTMLInputElement)) {
return;
}
this.newserverName = target.value;
}
When a user types Apollo into the input:
- The browser updates the input element's current value to
Apollo. - The browser dispatches an
inputevent. - Angular passes that event to
onUpdatingServerName. event.targetrefers to the element where the event started: the input.instanceof HTMLInputElementverifies that the target is truly an input element.- TypeScript now knows
targethas thevalueproperty. target.valuereturns the stringApollo.- The component assigns to .
Real World Use Cases
DOM event target narrowing is useful whenever a user action provides data through an HTML element:
- Search fields: read
HTMLInputElement.valueas the user types. - Checkboxes: read
HTMLInputElement.checkedafter a change. - File uploads: read
HTMLInputElement.filesfrom a file input. - Textareas: narrow to
HTMLTextAreaElementand readvalue. - Select menus: narrow to
HTMLSelectElementand read the selectedvalue. - Event delegation: a container handler checks whether
event.targetis a button, link, or input before acting.
Example for a checkbox:
onNewsletterChange(event: Event): void {
const input = event.target as HTMLInputElement;
this.isSubscribed = input.checked;
}
Real Codebase Usage
In production code, prefer patterns that make assumptions clear and keep unsafe assertions small.
Use a guard for reusable handlers
A shared handler may be called from different elements. Validate the target first:
function getInputValue(event: Event): string | undefined {
const { target } = event;
if (!(target instanceof HTMLInputElement)) {
return undefined;
}
return target.value;
}
Use an early return
Early returns avoid deeply nested if statements:
onInput(event: Event): void {
if (!(event.target instanceof HTMLInputElement)) return;
this.newserverName = event.target.value.trim();
}
Pass data rather than browser events
Common Mistakes
Accessing value directly on EventTarget
This fails because EventTarget does not define value:
// Error: Property 'value' does not exist on type 'EventTarget'.
this.newserverName = event.target.value;
Narrow or assert the target first.
Forgetting that target may be null
Even this is incomplete under strict null checking:
const target: EventTarget | null = event.target;
target.value;
Use an instanceof check, which handles both the element type and null:
if (event.target instanceof HTMLInputElement) {
console.(event..);
}
Comparisons
| Approach | Best use case | Safety |
|---|---|---|
event.target as HTMLInputElement | The template guarantees the handler is attached to an input | Compile-time assertion only; no runtime check |
event.target instanceof HTMLInputElement | Shared, delegated, or defensive event handlers | Runtime check plus TypeScript narrowing |
Pass value: string to the method | Component logic should not depend on DOM events | Keeps business logic simple and typed |
(event.target as any).value | Temporary compatibility workaround | Avoid when possible; removes type checking |
target and currentTarget also have different meanings:
| Property |
|---|
Cheat Sheet
// Input value: assertion
const value = (event.target as HTMLInputElement).value;
// Input value: safe runtime guard
if (event.target instanceof HTMLInputElement) {
const value = event.target.value;
}
// Checkbox state
if (event.target instanceof HTMLInputElement) {
const checked = event.target.checked;
}
// Select value
if (event.target instanceof HTMLSelectElement) {
const value = event.target.value;
}
// Textarea value
if (event.target instanceof HTMLTextAreaElement) {
const value = event.target.value;
}
EventTargetdoes not contain input-specific properties.event.targetmay be .
FAQ
Why does the browser console show value but TypeScript reports an error?
The console shows the actual runtime element. TypeScript sees the broader declared type, EventTarget | null, which could also represent objects without a value property.
What is the correct TypeScript type for a text input?
Use HTMLInputElement. It includes properties such as value, checked, files, and type.
Is event.target as HTMLInputElement safe?
It is safe when you know the event handler is only used by an <input>. If the handler can be reused or invoked from other elements, use instanceof HTMLInputElement instead.
Why does TypeScript say that event.target might be null?
The DOM event type allows a missing target in some situations. A type guard such as event.target instanceof HTMLInputElement handles this automatically.
Should I use target or currentTarget?
Mini Project
Description
Build a small Angular server-name field that reads input events safely, keeps the current value in component state, and displays a validation message. This demonstrates DOM type narrowing and separates obtaining user input from validating it.
Goal
Create an input handler that accepts only events from text inputs and stores a non-empty server name.
Requirements
Requirement 1
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.
Angular *ngFor: Fix “Can't Bind to ngFor” Errors
Learn why Angular cannot bind to ngFor, how structural directive microsyntax works, and how to import NgFor or CommonModule correctly.