Property code does not exist on type error

The Setup So, I was recently using Node's url module within TypeScript to be able to do so...

Joseph Barron

The Setup

So, I was recently using Node’s url module within TypeScript to be able to do some simple validation of user-provided URLs. According to the docs, when an invalid URL is supplied to the URL class, it throws a TypeError. Great! This is exactly what I wanted.

Next, all I had to do was catch that particular TypeError and give a helpful message to the user to let them know their URL was no good. Easy, all I need to do is write a try-catch statement and check the error’s code. Of course, the specific error code to look for is documented on an entirely different page for some reason. It was actually easier for me to just spin up a terminal and write a gibberish string into a new URL() call myself to determine that I was looking for "ERR_INVALID_URL".

The Problematic Code

try {
    const validUrl = new URL(url).href;
} catch (e) {
    if (e instanceof TypeError) {
        if (e.code === "ERR_INVALID_URL") {
            // Property 'code' does not exist on
            // type 'TypeError'. ts(2339)
        }
    }
}

Enter fullscreen mode

Exit fullscreen mode

Huh? What do you mean? The docs clearly stated that an Error in Node should have a code property, and TypeError extends Error… This didn’t make sense.

I used VS Code’s nifty «Go to Definition» feature to find the type definition for TypeError, which opened node_modulestypescriptliblib.es5.d.ts. I then found my way to the definition for the Error interface…

/* node_modulestypescriptliblib.es5.d.ts */
interface Error {
    name: string;
    message: string;
    stack?: string;
}

Enter fullscreen mode

Exit fullscreen mode

Oh! This was the interface of an Error you’d find in a browser environment.

But I was working with Node, and I already had the @types/node package installed… I had falsely assumed that this would somehow magically tell the TypeScript linter that I was catching a Node Error. How was I supposed to get TypeScript to infer that the TypeError I was handling most likely extended Node’s Error class, and had the extra code property I was looking for?

Search Engine Spelunking

After some confused finagling with my tsconfig.json and VS Code settings, I quickly gave up and went to Google. I soon after learned two things via random answers on StackOverflow:

  1. The type definition for the NodeJS Error class is declared in node_modules@typesnodeglobals.d.ts — and was accessible as NodeJS.ErrnoException. I wasn’t sure where this was officially documented, but alright!

    /* node_modules@typesnodeglobals.d.ts */
    interface ErrnoException extends Error {
            errno?: number;
            code?: string;
            path?: string;
            syscall?: string;
            stack?: string;
    }
    
  2. It was possible to use TypeScript’s type guards to create a function that I could use to check the error at runtime, so that I (and TypeScript) could be absolutely sure that this variable was a Node Error.

The example function from StackOverflow looked sort of like this:

function isError(error: any): error is NodeJS.ErrnoException {
    return error instanceof Error;
}

Enter fullscreen mode

Exit fullscreen mode

At a glance, this seemed like it would work… The function was running an instanceof check and used a «type predicate» (the error is NodeJS.ErrnoException part) to help TypeScript to do the type inference I was looking for. I could finally access the code property on the error without any dreaded red squiggly lines.

if (isError(e) && e instanceof TypeError) {
    if (e.code === "ERR_INVALID_URL") {
        // Hooray?
    }
}

Enter fullscreen mode

Exit fullscreen mode

But, I wasn’t totally satisfied. For one, there was nothing stopping me from passing things that weren’t errors to isError(). This was easily fixed by changing the the first argument of isError() to expect Error instead of any.

Secondly, it also felt inherently silly to have to run two instanceof checks every time I wanted to handle an error. (Truthfully, it’s not the worst thing in the world… but I believe that TypeScript should require developers to make as few runtime code changes as possible when transitioning from JavaScript.)

The Solution

After some experimenting, I managed to come up with the following function, which I tested with a couple of custom error classes to ensure that any additionally defined properties were preserved.

It turned out that the key was to make a generic function which acted as a typeguarded version of instanceof for Node.JS error handling, by doing the following things:

  1. Accepted two arguments that would be similar to the left-hand and right-hand sides of the instanceof operator.

  2. Enforced the first argument was of the Error class or a subclass.

  3. Enforced the second argument was a constructor for an Error or a subclass of Error.

  4. Ran the instanceof check.

  5. Used a type predicate to intersect the type of the first argument with the instance type of the error constructor in the second argument, as well as NodeJS.ErrnoException so that type inference would work as expected when used.

/**
 * A typeguarded version of `instanceof Error` for NodeJS.
 * @author Joseph JDBar Barron
 * @link https://dev.to/jdbar
 */
export function instanceOfNodeError<T extends new (...args: any) => Error>(
    value: Error,
    errorType: T
): value is InstanceType<T> & NodeJS.ErrnoException {
    return value instanceof errorType;
}

Enter fullscreen mode

Exit fullscreen mode

Examples

Original Use Case

try {
    const validUrl = new URL(url).href;
} catch (e) {
    if (instanceOfNodeError(e, TypeError)) {
        if (e.code === "ERR_INVALID_URL") {
            // Hooray!
        }
    }
}

Enter fullscreen mode

Exit fullscreen mode

Usage with Custom Error Classes

// Create our custom error classes.
class CoolError extends Error {
    foo: string = "Hello world.";
}

class VeryCoolError extends CoolError {
    bar: string = "Goodbye world.";
}

// Try throwing an error.
try {
    throw new CoolError();
} catch (e) {
    if (instanceOfNodeError(e, CoolError)) {
        // typeof e: CoolError & NodeJS.ErrnoException
        console.log(e.foo);
    } else if (instanceOfNodeError(e, VeryCoolError)) {
        // typeof e: VeryCoolError & NodeJS.ErrnoException
        console.log(e.foo, e.bar);
    } else {
        // typeof e: any
        console.log(e);
    }
}

// Try passing something that's not an error.
const c = NaN;
if (instanceOfNodeError(c, CoolError)) {
    // Argument of type 'number' is not assignable to
    // parameter of type 'Error'. ts(2345)
    console.log(c.foo);
}

const d = new CoolError();
if (instanceOfNodeError(d, Number)) {
    // Argument of type 'NumberConstructor' is not assignable
    // to parameter of type 'new (...args: any) => Error'.
    console.log(d.foo);
}

Enter fullscreen mode

Exit fullscreen mode

You might be wondering why in that one else clause, the type of e was any… well, TypeScript can’t guarantee the type of e is anything in particular, because JavaScript lets you throw literally anything. Thanks JavaScript…

Summary

After utilizing both generics and type guards, I managed to get TypeScript to correctly infer the shape of the errors I was handling in a Node.js environment without performing redundant instanceof checks. However, the solution still wasn’t perfect, since I probably did sacrifice some amount of compute overhead and space on the call stack to be able to call the instanceOfNodeError() function compared to the bog-standard instanceof call I would have done in JavaScript.


It’s possible that in the future, there could be an update to the @types/node package that would merge the NodeJS.ErrnoException type with the global Error type.

One could argue that since not all errors in Node.js will have the code property (or the other properties on the ErrnoException type), that it doesn’t make sense to do such a reckless merging of types. However, I don’t see a lot of harm when all of the properties of ErrnoException are marked optional.

Otherwise, they have to be manually added to any modules that might throw an Error with the properties of ErrnoException, per the details of this rather old commit responsible for implementing it within the fs module. However, this still leaves us with a problem when these ErrnoException errors can be thrown by the constructors of classes in Node.js, like the URL class does.

For that, the only alternative fix I could think of would be for TypeScript to add some sort of throws syntax for function/constructor signatures — which there seems to be an open issue for from 2016 in the microsoft/TypeScript GitHub repo.

How to Fix the “Property does not exist on type {}” Error in TypeScript 📌[All Method]️
How to Fix the Property does not exist on type Error in TypeScript All Method

The blog will help about How to Fix the “Property does not exist on type {}” Error in TypeScript & learn how to solve different problems that come from coding errors. If you get stuck or have questions at any point,simply comment below.
Question: What is the best way to approach this problem? Answer: Check out this blog code to learn how to fix errors How to Fix the “Property does not exist on type {}” Error in TypeScript. Question: “What should you do if you run into code errors?” Answer:”You can find a solution by following this blog.

Assigning properties to JavaScript objects is quite simple.

let obj = {}
obj.key1 = 1;
obj['key2'] = 'dog';

This would give me these values for obj:

obj: {
   key1: 1, 
   key2: 'dog'
}

The Problem

When we head over to TypeScript, running this code gives us the error below.

let obj = {}
obj.key1 = 1;
Property 'key1' does not exist on type '{}'.

How do we work with JSON objects in TypeScript?

Solution 1: The Quick Fix

In TypeScript, we can type a function by specifying the parameter types and return types.

Similarly, we need to type our objects, so that TypeScript knows what is and isn’t allowed for our keys and values.

Quick and dirty. A quick and dirty way of doing this is to assign the object to type any. This type is generally used for dynamic content of which we may not know the specific type. Essentially, we are opting out of type checking that variable.

let obj: any = {}
obj.key1 = 1;
obj['key2'] = 'dog';

But then, what’s the point of casting everything to type any just to use it? Doesn’t that defeat the purpose of using TypeScript?

Well, that’s why there’s the proper fix.

Solution 2: The Proper Fix

Consistency is key. In order to stay consistent with the TypeScript standard, we can define an interface that allows keys of type string and values of type any.

interface ExampleObject {
    [key: string]: any
}
let obj: ExampleObject = {};
obj.key1 = 1;
obj['key2'] = 'dog';

What if this interface is only used once? We can make our code a little more concise with the following:

let obj: {[k: string]: any} = {};
obj.key1 = 1;
obj['key2'] = 'dog';

Solution 3: The JavaScript Fix

Pure JavaScript. What if we don’t want to worry about types? Well, don’t use TypeScript 😉

Or you can use Object.assign().

let obj = {};
Object.assign(obj, {key1: 1});
Object.assign(obj, {key2: 'dog'});

What an exciting time to be alive.

Revise the code and make it more robust with proper test case and check an error there before implementing into a production environment.
Now you can solve your code error in less than a minute.

Errors

Edit this page on GitHub

Errors are an inevitable fact of software development. SvelteKit handles errors differently depending on where they occur, what kind of errors they are, and the nature of the incoming request.

Error objectspermalink

SvelteKit distinguishes between expected and unexpected errors, both of which are represented as simple { message: string } objects by default.

You can add additional properties, like a code or a tracking id, as shown in the examples below. (When using TypeScript this requires you to redefine the Error type as described in type safety).

Expected errorspermalink

An expected error is one created with the error helper imported from @sveltejs/kit:

src/routes/blog/[slug]/+page.server.js

ts

import { error } from '@sveltejs/kit';

import * as db from '$lib/server/database';

/** @type {import('./$types').PageServerLoad} */

export async function load({ params }) {

const post = await db.getPost(params.slug);

if (!post) {

throw error(404, {

message: 'Not found'

});

}

return { post };

}

src/routes/blog/[slug]/+page.server.ts

ts

import { error } from '@sveltejs/kit';

import * as db from '$lib/server/database';

import type { PageServerLoad } from './$types';

export const load = (async ({ params }) => {

const post = await db.getPost(params.slug);

if (!post) {

throw error(404, {

message: 'Not found'

});

}

return { post };

}) satisfies PageServerLoad;

This tells SvelteKit to set the response status code to 404 and render an +error.svelte component, where $page.error is the object provided as the second argument to error(...).

src/routes/+error.svelte

<script>
  import { page } from '$app/stores';
</script>

<h1>{$page.error.message}</h1>

You can add extra properties to the error object if needed…

throw error(404, {
  message: 'Not found',
	code: 'NOT_FOUND'
});

…otherwise, for convenience, you can pass a string as the second argument:

throw error(404, { message: 'Not found' });
throw error(404, 'Not found');

Unexpected errorspermalink

An unexpected error is any other exception that occurs while handling a request. Since these can contain sensitive information, unexpected error messages and stack traces are not exposed to users.

By default, unexpected errors are printed to the console (or, in production, your server logs), while the error that is exposed to the user has a generic shape:

{ "message": "Internal Error" }

Unexpected errors will go through the handleError hook, where you can add your own error handling — for example, sending errors to a reporting service, or returning a custom error object.

src/hooks.server.js

ts

import * as Sentry from '@sentry/node';

Sentry.init({/*...*/})

/** @type {import('@sveltejs/kit').HandleServerError} */

Type '{ message: string; code: any; }' is not assignable to type 'MaybePromise<void | Error>'. Object literal may only specify known properties, and 'code' does not exist in type 'Error | Promise<void | Error>'.
Property 'code' does not exist on type '{}'.
2322
2339
Type '{ message: string; code: any; }' is not assignable to type 'MaybePromise<void | Error>'. Object literal may only specify known properties, and 'code' does not exist in type 'Error | Promise<void | Error>'.
Property 'code' does not exist on type '{}'.

export function handleError({ error, event }) {

// example integration with https://sentry.io/

Sentry.captureException(error, { event });

return {

message: 'Whoops!',

code: error?.code ?? 'UNKNOWN'

};

}

src/hooks.server.ts

ts

import * as Sentry from '@sentry/node';

import type { HandleServerError } from '@sveltejs/kit';

Sentry.init({/*...*/})

Property 'code' does not exist on type '{}'.2339Property 'code' does not exist on type '{}'.

export const handleError = (({ error, event }) => {

// example integration with https://sentry.io/

Sentry.captureException(error, { event });

return {

message: 'Whoops!',

code: error?.code ?? 'UNKNOWN'

};

}) satisfies HandleServerError;

Make sure that handleError never throws an error

Responsespermalink

If an error occurs inside handle or inside a +server.js request handler, SvelteKit will respond with either a fallback error page or a JSON representation of the error object, depending on the request’s Accept headers.

You can customise the fallback error page by adding a src/error.html file:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>%sveltekit.error.message%</title>
  </head>
  <body>
    <h1>My custom error page</h1>
    <p>Status: %sveltekit.status%</p>
    <p>Message: %sveltekit.error.message%</p>
  </body>
</html>

SvelteKit will replace %sveltekit.status% and %sveltekit.error.message% with their corresponding values.

If the error instead occurs inside a load function while rendering a page, SvelteKit will render the +error.svelte component nearest to where the error occurred. If the error occurs inside a load function in +layout(.server).js, the closest error boundary in the tree is an +error.svelte file above that layout (not next to it).

The exception is when the error occurs inside the root +layout.js or +layout.server.js, since the root layout would ordinarily contain the +error.svelte component. In this case, SvelteKit uses the fallback error page.

Type safetypermalink

If you’re using TypeScript and need to customize the shape of errors, you can do so by declaring an App.Error interface in your app (by convention, in src/app.d.ts, though it can live anywhere that TypeScript can ‘see’):

src/app.d.ts

declare global {
  namespace App {
    interface Error {
			code: string;
			id: string;
    }
  }
}

export {};

This interface always includes a message: string property.

Answer by Kendall Allison

This happens because when you start the application, The server is actually serving the bundles(JavaScript/CSS/HTML… output files) stored in the dist folder. Sometimes, when you make changes in your code, the changes don’t reflect in your bundles, which will lead to the server still using the old bundles. ,It usually happens when you develop Angular applications. To solve this just shut down the server & start it again:,

This behavior is also happening with ionic 4 CLI. So if a service is missing it’s members restart ionic serve will help.

– Dave Gööck
Feb 12 ’19 at 14:10

It usually happens when you develop Angular applications. To solve this just shut down the server & start it again:

$ ng serve 

Answer by Alexis Novak

This happens because when you start the application, The server is actually serving the bundles(JavaScript/CSS/HTML… output files) stored in the dist folder. Sometimes, when you make…,It usually happens when you develop Angular applications. To solve this just shut down the server & start it again:,Built on Forem — the open source software that powers DEV and other inclusive communities.

It usually happens when you develop Angular applications. To solve this just shut down the server & start it again:

$ ng serve 

Answer by Celine Manning

So what is going here? We have defined an empty object first and then tried to assign it the name property. This is just plain Javascript code, and Typescript should allow us to write that transparently. So why the error message?,If you enjoyed this post, have also a look also at other popular posts that you might find interesting:,We are going to understand it by providing another example, have a look at this and try to guess if it compiles, and if not what is the error message:

If we are not familiar with how the Typescript Type system works, we might be surprised to realize that this actually does not compile. So why is that? Let’s have a look at the error message we get:

Error:(54, 6) TS2339:Property 'name' does not exist on type '{}'.

If we hover over the user variable, we can see the inferred type. In Webstorm, if we click the variable and hit Ctrl+Shift+P, we get the following inferred type:

type: {}

Again it might be a bit surprising that this code does not compile. Here is the error message:

Error:(59, 8) TS2339:Property 'lessonCount' does not exist on type '{ name: string; }'.

And if we check what is the inferred type of the variable course, we get this type:

type: {name:string}

But the line course = named does not compile, and we get the following error:

Error:(73, 1) TS2322:Type 'Named' is not assignable to type 'Course'. Property 'lessonCount' is missing in type 'Named'.

Answer by Kamari Kelly

I know I can fix the error by declaring the variable.,When compiled/transpiled through TypeScript it generates error TS2339: Property ‘myclassvar’ does not exist on type ‘MyClass’.,Can it surely be a duplicate of the ticket called «Allow declaring class members within a constructor»?

class MyClass {
    constructor(){
        this.myclassvar = 'abc';
    }
}

Answer by Cooper Guerrero

While I was trying the below example – Passing recipe data with property binding I got the following error.,For example, to pass recipe data with property binding and use ngFor loop refer below section.,When I was trying to pass component data with property binding, I got the following typescript error : Property does not exist on value of type. This tutorial guides you how to resolve this error and also guides on how to pass recipe data with property binding.

While I was trying the below example – Passing recipe data with property binding I got the following error.

Angular is running in the development mode. Call enableProdMode() to enable the production mode.
client:52 [WDS] Live Reloading enabled.
client:150 [WDS] Errors while compiling. Reload prevented.
errors @ client:150
client:159 src/app/recipes/recipe-list/recipe-item/recipe-item.component.html:5:26 - error TS2339: Property 'recipes' does not exist on type 'RecipeItemComponent'.

5    *ngFor="let recipe of recipes">
                           ~~~~~~~

  src/app/recipes/recipe-list/recipe-item/recipe-item.component.ts:5:16
    5   templateUrl: './recipe-item.component.html',
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component RecipeItemComponent.

Note, the parent-child relationship for the below example is as follows.

--recipes
---- recipe.model.ts
---- recipe-detail
---- recipe-list
------ recipe-item

recipes/recipe-list/recipe-item/recipe-item.component.html

<a href="#" 
   class="list-group-item clearfix">
    <div class="pull-left">
        <h4 class="list-group-item-heading">{{ recipe.name }}</h4>
        <p class="list-group-item-text">{{ recipe.description }}</p>
    </div>
    <span class="pull-right">
        <img 
             [src] = "recipe.imagePath"
             alt="{{ recipe.name }}" 
             class="img-responsive" 
             style="max-height: 50px;"> 
    </span>
</a>

recipes/recipe-list/recipe-item/recipe-item.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-recipe-item',
  templateUrl: './recipe-item.component.html',
  styleUrls: ['./recipe-item.component.css']
})
export class RecipeItemComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}

For example, to pass recipe data with property binding and use ngFor loop refer below section.

<div class="row">
    <div class="col-xs-12">
        <div class="pull-left">
            <h3>My Recipe List</h3>
        </div>   
    </div>
</div>
<hr>
<div class="row">
    <div class="col-xs-12">        
        <app-recipe-item 
          *ngFor="let recipe of recipes"
          [recipe] = "recipe"></app-recipe-item>
    </div>
</div>
<hr>
<div class="row">
    <div class="col-xs-12">
        <div class="pull-right">
            <button class="btn btn-success">Add Recipe</button>
        </div>        
    </div>
</div>



recipes/recipe-list/recipe-list.component.ts

import { Component, OnInit } from '@angular/core';
import { Recipe } from '../recipe.model';

@Component({
  selector: 'app-recipe-list',
  templateUrl: './recipe-list.component.html',
  styleUrls: ['./recipe-list.component.css']
})
export class RecipeListComponent implements OnInit {

  recipes: Recipe[] = [
    new Recipe('Recipe 1', 'This is our first recipe', 'https://lilluna.com/wp-content/uploads/2017/10/spanish-rice-resize-6.jpg'),
    new Recipe('Recipe 2', 'This is our second recipe', 'https://food.fnr.sndimg.com/content/dam/images/food/fullset/2020/07/14/0/FNK_20-Minute-Sausage-And-Pepper-Ravioli-Skillet_H_s4x3.jpg.rend.hgtvcom.441.331.suffix/1594757098344.jpeg'),
    new Recipe('Recipe 3', 'This is our third recipe', 'https://images.squarespace-cdn.com/content/v1/5c089f01f93fd410a92e642a/1589512502567-CNOAIL05BVT1TI0422P2/ke17ZwdGBToddI8pDm48kLkXF2pIyv_F2eUT9F60jBl7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0iyqMbMesKd95J-X4EagrgU9L3Sa3U8cogeb0tjXbfawd0urKshkc5MgdBeJmALQKw/pheasant+back+burger+recipe.jpeg'),
    new Recipe('Recipe 4', 'This is our fourth recipe', 'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQunf0MIpWZn3rjR-mo4u9_HKsL0Ud3SV8WTQ&usqp=CAU'),
    new Recipe('Recipe 5', 'This is our fifth recipe', 'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQ_9l39e7G5y_ENz6hL6l5KhaJuroOrbzqs0Q&usqp=CAU')
  ];

  constructor() { }

  ngOnInit(): void {
  }

}

recipes/recipe.model.ts

export class Recipe {
    public name : string;
    public description : string;
    public imagePath : string;

    constructor(name : string, description : string, imagePath : string){
        this.name = name;
        this.description = description;
        this.imagePath = imagePath;
    } 
}

I figured out the reason why I was getting error Property ‘recipes’ does not exist on type ‘RecipeItemComponent’. I forgot to add the following statement in the RecipeItemComponent class.

  @Input() recipe: Recipe;

recipe-item.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { Recipe } from '../../recipe.model';

@Component({
  selector: 'app-recipe-item',
  templateUrl: './recipe-item.component.html',
  styleUrls: ['./recipe-item.component.css']
})
export class RecipeItemComponent implements OnInit {

  @Input() recipe: Recipe;

  constructor() { }

  ngOnInit(): void {
  }

}

Answer by Lincoln Giles

Property value does not exist on type EventTarget Example,Property ‘value’ does not exist on type ‘EventTarget’ Error is a common error in Angular. It shows up when you try to access the value property of an HTML element during event binding.,The solution is to cast the event.target to appropriate HTML element as shown below

This error is flagged by the TypeScript compiler.

The $event in both examples are of type HTMLElement. It can represent any HTML Element. Hence the value property is not guaranteed to exist in the $event.target.

$event

This error is flagged by the TypeScript compiler.

The $event in both examples are of type HTMLElement. It can represent any HTML Element. Hence the value property is not guaranteed to exist in the $event.target.

HTMLElement

This error is flagged by the TypeScript compiler.

The $event in both examples are of type HTMLElement. It can represent any HTML Element. Hence the value property is not guaranteed to exist in the $event.target.

value

This error is flagged by the TypeScript compiler.

The $event in both examples are of type HTMLElement. It can represent any HTML Element. Hence the value property is not guaranteed to exist in the $event.target.

$event.target

Answer by Harvey Brady

import { of } from 'rxjs';

Answer by Wayne Moody

The EventTarget type does not inherit from the Element type which is why TypeScript fails to recognize properties such as id, class, etc. that we would expect to exist on a typical Element object.,
Without setting the proper type for the event target, we’ll get the «Property ‘value’ does not exist on type ‘EventTarget'» error while trying to get the value property of the input element. Therefore, as discussed earlier, we need to assert the type we expect the event target to be like in the following way for example:
,
Alternatively, we can also do the following if we only need to use the target property from the event:

Let’s suppose we have the following HTML element:

<div id="foo"></div>

With the following code snippet we will receive the element above as an event target in our event listener:

const elem = document.getElementById('foo');

elem.addEventListener('test', function (e) {
    // Property 'id' does not exist on type 'EventTarget'.
    console.log(e.target.id); // 'foo'
}, false);

elem.dispatchEvent(new Event('test'));

To make TypeScript understand the correct type for the event target, we can specify it like so:

const elem = document.getElementById('foo');

elem.addEventListener('test', function (e) {
    const target = e.target as Element;
    console.log(target.id); // 'foo'
}, false);

elem.dispatchEvent(new Event('test'));

We can also inline it like so:

(e.target as Element).id

Alternatively, we can also do the following if we only need to use the target property from the event:

const elem = document.getElementById('foo');

elem.addEventListener('test', function (e: { target: Element }) {
    console.log(e.target.id); // 'foo'

    // Property 'type' does not exist on type '{ target: HTMLInputElement; }'.
    console.log(e.type);
}, false);

elem.dispatchEvent(new Event('test'));

As it is evident from the example above, after specifying the correct type for e.target it works fine. However, other properties (such as e.type, etc.) would throw a TypeScript error. If we need to access those other properties of the event as well, we could do so in the following way:

const elem = document.getElementById('foo');

elem.addEventListener('test', function (e: Event & { target: Element }) {
    console.log(e.target.id); // 'foo'

    // other Event object properties are recognized too now:
    console.log(e.type); // 'test'
}, false);

elem.dispatchEvent(new Event('test'));

We can, of course, get more specific with the type of the target events. For example, let’s suppose we wanted to get the value attribute of the following target input element:

<input id="foo" type="text" value="bar" />

Without setting the proper type for the event target, we’ll get the «Property 'value' does not exist on type 'EventTarget'» error while trying to get the value property of the input element. Therefore, as discussed earlier, we need to assert the type we expect the event target to be like in the following way for example:

const elem = document.getElementById('foo');

elem.addEventListener('test', function (e) {
    console.log((e.target as HTMLInputElement).value); // 'bar'
}, false);

elem.dispatchEvent(new Event('test'));

Assuming that the event target is <input type="file">, we can fix this error like so:

// Property 'files' does not exist on type 'EventTarget'.
e.target.files;

// possible fix:
(e.target as HTMLInputElement).files;

Assuming that the event target is an HTML audio/video element, we can fix this error like so:

// Property 'controls' does not exist on type 'EventTarget'.
e.target.controls;

// possible fixes:
(e.target as HTMLMediaElement).controls;
(e.target as HTMLVideoElement).controls;
(e.target as HTMLAudioElement).controls;

Here, using the HTMLMediaElement should be sufficient. However, we can also do the following when the target element can be either an audio or a video element:

type MediaType = HTMLVideoElement | HTMLAudioElement;
(e.target as MediaType).form;

Assuming that the event target is an HTML input element, we can fix this error like so:

// Property 'form' does not exist on type 'EventTarget'.
e.target.form;

// possible fix:
(e.target as HTMLInputElement).form;

Assuming that the event target is an HTML textarea element, we can fix this error like so:

// Property 'form' does not exist on type 'EventTarget'.
e.target.form;

// possible fix:
(e.target as HTMLTextAreaElement).form;

If the target element can be either an input or a textarea element, we can create a new intersection type like so:

// Property 'form' does not exist on type 'EventTarget'.
e.target.form;

// possible fix:
type InputType = HTMLInputElement | HTMLTextAreaElement;
(e.target as InputType).form;

Assuming that the event target is an HTML <input type="radio"> or <input type="checkbox"> element, we can fix this error like so:

// Property 'checked' does not exist on type 'EventTarget'.
e.target.checked;

// possible fix:
(e.target as HTMLInputElement).checked;

Assuming that the event target is an HTML <img> element, we can fix this error like so:

// Property 'src' does not exist on type 'EventTarget'.
e.target.src;

// possible fix:
(e.target as HTMLImageElement).src;

Assuming that the event target is an HTML <source> element, we can fix this error like so:

// Property 'src' does not exist on type 'EventTarget'.
e.target.src;

// possible fix:
(e.target as HTMLSourceElement).src;

The classList property exists on every HTML element, so we could use Element, HTMLElement or a more specific type (for e.g. HTMLInputElement, etc.). For example:

// Property 'classList' does not exist on type 'EventTarget'.
e.target.classList;

// possible fixes:
(e.target as Element).classList;
(e.target as HTMLElement).classList;
// etc.

The parentNode property exists on every HTML element, so we could use Element, HTMLElement or a more specific type (for e.g. HTMLInputElement, etc.). For example:

// Property 'parentNode' does not exist on type 'EventTarget'.
e.target.parentNode;

// possible fixes:
(e.target as Element).parentNode;
(e.target as HTMLElement).parentNode;
// etc.

How to Fix «Property ‘…’ does not exist on type ‘EventTarget'» TypeScript Error?

Find out why this TypeScript error happens and how to fix it

  • 24 Oct, 2020

  • 6 min read

Let’s suppose we have the following HTML element:

<div id="foo"></div>

With the following code snippet we will receive the element above as an event target in our event listener:

const elem = document.getElementById('foo');

elem.addEventListener('test', function (e) {
    // Property 'id' does not exist on type 'EventTarget'.
    console.log(e.target.id); // 'foo'
}, false);

elem.dispatchEvent(new Event('test'));

This code runs perfectly fine because we know we’re expecting the event target to be an HTML element, and we are certain that the HTML element has the property id. However, TypeScript complains about the id property not existing on the EventTarget type. This is because:

  • By default an event target element has an EventTarget type in TypeScript;
  • The EventTarget type does not inherit from the Element type which is why TypeScript fails to recognize properties such as id, class, etc. that we would expect to exist on a typical Element object.

Why Does the EventTarget Type Not Inherit From Element Type?

The reason this is the case is simply because all event targets might not be HTML elements. For example the event target can be also be XMLHttpRequest, FileReader, AudioNode, AudioContext, etc.

How to Fix This Error?

To make TypeScript understand the correct type for the event target, we can specify it like so:

const elem = document.getElementById('foo');

elem.addEventListener('test', function (e) {
    const target = e.target as Element;
    console.log(target.id); // 'foo'
}, false);

elem.dispatchEvent(new Event('test'));

We can also inline it like so:

(e.target as Element).id

Alternatively, we can also do the following if we only need to use the target property from the event:

const elem = document.getElementById('foo');

elem.addEventListener('test', function (e: { target: Element }) {
    console.log(e.target.id); // 'foo'

    // Property 'type' does not exist on type '{ target: HTMLInputElement; }'.
    console.log(e.type);
}, false);

elem.dispatchEvent(new Event('test'));

As it is evident from the example above, after specifying the correct type for e.target it works fine. However, other properties (such as e.type, etc.) would throw a TypeScript error. If we need to access those other properties of the event as well, we could do so in the following way:

const elem = document.getElementById('foo');

elem.addEventListener('test', function (e: Event & { target: Element }) {
    console.log(e.target.id); // 'foo'

    // other Event object properties are recognized too now:
    console.log(e.type); // 'test'
}, false);

elem.dispatchEvent(new Event('test'));

We can, of course, get more specific with the type of the target events. For example, let’s suppose we wanted to get the value attribute of the following target input element:

<input id="foo" type="text" value="bar" />

Without setting the proper type for the event target, we’ll get the «Property 'value' does not exist on type 'EventTarget'» error while trying to get the value property of the input element. Therefore, as discussed earlier, we need to assert the type we expect the event target to be like in the following way for example:

const elem = document.getElementById('foo');

elem.addEventListener('test', function (e) {
    console.log((e.target as HTMLInputElement).value); // 'bar'
}, false);

elem.dispatchEvent(new Event('test'));

In the code above we used a more specific type (i.e. HTMLInputElement) because the value property does not exist on the generic Element type. The HTMLInputElement type inherits from the Element type though. Therefore, it will have the generic element properties (such as id, class, etc.) as well as the more specific ones that exclusively exist on the HTMLInputElement object (such as value, validity, etc.).

Common Errors

Let’s see a few more examples of some common errors associated with this issue:

Property ‘files’ does not exist on type ‘EventTarget’:

Assuming that the event target is <input type="file">, we can fix this error like so:

// Property 'files' does not exist on type 'EventTarget'.
e.target.files;

// possible fix:
(e.target as HTMLInputElement).files;

Property ‘controls’ does not exist on type ‘EventTarget’:

Assuming that the event target is an HTML audio/video element, we can fix this error like so:

// Property 'controls' does not exist on type 'EventTarget'.
e.target.controls;

// possible fixes:
(e.target as HTMLMediaElement).controls;
(e.target as HTMLVideoElement).controls;
(e.target as HTMLAudioElement).controls;

Here, using the HTMLMediaElement should be sufficient. However, we can also do the following when the target element can be either an audio or a video element:

type MediaType = HTMLVideoElement | HTMLAudioElement;
(e.target as MediaType).form;

Property ‘form’ does not exist on type ‘EventTarget’:

Assuming that the event target is an HTML input element, we can fix this error like so:

// Property 'form' does not exist on type 'EventTarget'.
e.target.form;

// possible fix:
(e.target as HTMLInputElement).form;

Assuming that the event target is an HTML textarea element, we can fix this error like so:

// Property 'form' does not exist on type 'EventTarget'.
e.target.form;

// possible fix:
(e.target as HTMLTextAreaElement).form;

If the target element can be either an input or a textarea element, we can create a new intersection type like so:

// Property 'form' does not exist on type 'EventTarget'.
e.target.form;

// possible fix:
type InputType = HTMLInputElement | HTMLTextAreaElement;
(e.target as InputType).form;

Property ‘checked’ does not exist on type ‘EventTarget’:

Assuming that the event target is an HTML <input type="radio"> or <input type="checkbox"> element, we can fix this error like so:

// Property 'checked' does not exist on type 'EventTarget'.
e.target.checked;

// possible fix:
(e.target as HTMLInputElement).checked;

Property ‘src’ does not exist on type ‘EventTarget’:

Assuming that the event target is an HTML <img> element, we can fix this error like so:

// Property 'src' does not exist on type 'EventTarget'.
e.target.src;

// possible fix:
(e.target as HTMLImageElement).src;

Assuming that the event target is an HTML <source> element, we can fix this error like so:

// Property 'src' does not exist on type 'EventTarget'.
e.target.src;

// possible fix:
(e.target as HTMLSourceElement).src;

Property ‘classList’ does not exist on type ‘EventTarget’:

The classList property exists on every HTML element, so we could use Element, HTMLElement or a more specific type (for e.g. HTMLInputElement, etc.). For example:

// Property 'classList' does not exist on type 'EventTarget'.
e.target.classList;

// possible fixes:
(e.target as Element).classList;
(e.target as HTMLElement).classList;
// etc.

Property ‘parentNode’ does not exist on type ‘EventTarget’:

The parentNode property exists on every HTML element, so we could use Element, HTMLElement or a more specific type (for e.g. HTMLInputElement, etc.). For example:

// Property 'parentNode' does not exist on type 'EventTarget'.
e.target.parentNode;

// possible fixes:
(e.target as Element).parentNode;
(e.target as HTMLElement).parentNode;
// etc.

Hope you found this post useful. It was published 24 Oct, 2020. Please show your love and support by sharing this post.

  • Web Development
  • TypeScript
  • JavaScript
  • Frontend
  • Node.js
  • Backend

Понравилась статья? Поделить с друзьями:
  • Pronight fatal error ue4
  • Promise обработка ошибок
  • Promise reject throw error
  • Promise error handling
  • Promise all catch error