JavaScript: Trouble accessing .target property for click event in EventTarget object

After converting my project from regular JavaScript to TypeScript, I encountered an issue where the target property of a base class EventTarget was not being recognized by TypeScript. This property worked perfectly fine in JS, so it must exist. Could it be that I'm incorrectly typing this variable?

I attempted to type the variable as Event, MouseEvent, HTMLDivElement, or HTMLAnchorElement, but none of these resolved the error regarding the missing target property.

const findClickedTab = (tabArray: object[], event: Event) => {
  const clickedTabArray = tabArray.filter(tabId => tabId === event.target.id);

 // irrelevant stuff removed
};

// caller of above function, which attaches to the event listener
const switchSection = event => {  
  const tabIdsArrayOfStrings = getTabIds();

  const clickedTabIdString = findClickedTab(tabIdsArrayOfStrings, event);

};

document.addEventListener('click', switchSection);

Update 1

My tsconfig.json file includes files/folders outside of ./templates, such as ./semantic, which is on the same level as ./templates. Here's a snippet of my tsconfig.json:

{
  "compilerOptions" : {
    "outDir" : "./compiledJs",
    "allowJs" : true,
    "module" : "commonjs",
    "target" : "es5",
    "sourceMap" : true
  },
  "include" : ["./templates/**/*"],
  "exclude" : [
    "node_modules"
  ]
}

https://i.sstatic.net/79TI1.jpg

Update 2

Adding "lib" : ["dom"] to my tsconfig.json and changing the variable typing from EventTarget to Event fixed the linting error for target. However, now there is an error with id (nested under target). PhpStorm 2019.2 indicates that id is not a property of EventTarget.

Updated tsconfig.json:

{
  "compilerOptions" : {
    "outDir" : "./compiledJs",
    "allowJs" : true,
    "module" : "commonjs",
    "target" : "es5",
    "sourceMap" : true
  },
  "include" : ["./templates/**/*"],
  "exclude" : [
    "node_modules"
  ],
  "lib" : ["dom"]
}

Answer №1

When attaching an event to the document, you are essentially listening for clicks on any of the document elements that bubble up to the document itself. This means that the target, where the event originated from, can be any element including the document itself. [evidence needed]

If your goal is to specifically find an element with a certain id, you can utilize a type guard.

const isElementWithId = (t: EventTarget): t is Element => 
   (t as Element).id !== undefined;

const findClickedTab = (tabArray: string[], event: Event) => {
    if (event.target && isElementWithId(event.target)) {
        const target: Element = event.target;
     // at this point, we are sure that event.target is an Element with an optional id property
     const clickedTabArray = tabArray.filter(tabId => tabId === target.id); 
  }

 // irrelevant details omitted
};

// calling the above function and attaching it to an event listener
const switchSection = (event: Event) => {  
  const tabIdsArrayOfStrings = getTabIds();
  const clickedTabIdString = findClickedTab(tabIdsArrayOfStrings, event);

};

document.addEventListener('click', switchSection);

Furthermore, make sure that your tabArray parameter is of type string[] in order to compare it with the id property.

Note: If you are searching for a specific element type (e.g., an anchor), there's a more efficient way to verify if the element is of that type:

export const isAnchor = (e: EventTarget): e is HTMLAnchorElement =>
    (e as Element).tagName && (e as Element).tagName == 'A'

tagName represents the uppercased qualified name in HTML 5

Answer №2

To resolve the compile time error, I used the syntax (variable as objectType) to assert the target property from an EventTarget to an HTMLAnchorElement object:

const clickedTab: string[] = tabArray.filter(tabId => tabId === (event.target as HTMLAnchorElement).id); 

In addition, I found the proper object type (HTMLAnchorElement) by logging the value of event.target.constructor.name.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the differences between initializing class members and using setters and getters in Typescript

Here is the code snippet that I am working with: export class Myclass { private _someVal = 2; public get someVal() { return this._someVal; } public set someVal(val) { this._someVal = val; } } In my template, I have <span&g ...

Step-by-step guide on how to index timestamp type using Knex.js

I'm in the process of indexing the created_at and updated_at columns using knex js. However, when I try to use the index() function, I encounter the following error: Property 'index' does not exist on type 'void' await knex.sche ...

Convert a TypeScript array of strings to a boolean array: a step-by-step guide

Upon receiving a list of objects from the front end as: item=["false","true"] I proceed to check a column within my records to identify values containing "true" or "false" using the following code: this.records.filter(x=> items.includes(x.column)) Unf ...

Issue with Material Sort functionality when null objects are present

I've encountered an issue with my code. I created a feature that adds empty rows if there are less than 5 rows, but now the sort function is no longer functioning properly. Strangely, when I remove the for loop responsible for adding empty rows, the s ...

The issue in Angular2 viewmodel where the boolean value fails to update the *ngIf template

I'm seeking assistance with an unusual issue in my Angular2 and Typescript application. Within my template, I have the following HTML utilizing ngIf: <div *ngIf="loading" class="row"> <div class="small-3 small-centered columns" > ...

Angular 2: Issue with disabled functionality not functioning correctly

In my TypeScript code, I have created a boolean variable called readOnlyMode. When this variable is set to true, all elements should be disabled. To achieve this, I am using [disabled]="readOnlyMode" in the HTML for elements that need to be disabled. Howev ...

Is the Cyrillic encoding feature not functioning properly in Angular 4 with .Net Core 2?

Struggling with handling Cyrillic characters in my current project. Utilizing .Net Core 2 along with Angular 4.2.5 I've noticed that displaying a string in the templates using {{ someCyrillicString }} works fine. However, encountering issues when tryi ...

What is the best way to invoke a function with multiple parameters in TypeScript?

I have a function that manipulates a specified query string, along with another version that always uses window.location.search. Here is the code snippet: class MyClass { public changeQuery(query: string; exclude: boolean = true; ...values: string[]): st ...

Failed to retrieve values from array following the addition of a new element

Does anyone have a solution for this problem? I recently added an element to my array using the push function, but when I tried to access the element at position 3, it wasn't defined properly processInput(inputValue: any): void { this.numOfIma ...

Using Typescript and React to manage controlled components and selecting a single checkbox within a group

all. I am currently working on a controlled component in Storybook using React and Typescript. When my Checkbox is uncontrolled, it works perfectly fine. However, I am facing some challenges with the logic and thought process when transitioning it to a ...

The button's status changes to disabled until I click outside the input field in Angular

I am currently facing an issue with a form (heat index calculator) that requires 2 inputs - a dropdown and a button. The button is disabled when there are no inputs or if the inputs are invalid. Everything works correctly, except for the fact that even whe ...

Enabling non-declarative namespaces in React using Typescript: A beginner's guide

I'm diving into the React environment integrated with Typescript, but I still have some confusion about its inner workings. I really hope to receive thorough answers that don't skip any important details. I came across a solution that involves d ...

What is the best way to import modules in Typescript/Javascript synchronously during runtime?

I have a Typescript class where I am attempting to perform a synchronous import, however, the import is being executed asynchronously. My code snippet looks like this: --------------100 lines of code-------------------- import('../../../x/y/z') ...

Trouble Integrating svgr/webpack with Webpack 5 and SingleSpa

I've been grappling with this issue for the past week. Despite scouring through numerous Stack Overflow threads and reading the SVGR/WEBPACK documentation, I haven't been able to find a solution. I decided to upgrade an old React single-spa appl ...

React doesn't have file upload configured to update the state

I am working on integrating a file upload button that sends data to an API. To ensure only the button triggers the upload dialog and not the input field, I have set it up this way. Issue: The File is not being saved to state, preventing me from using a ...

What exactly is the data type of setInterval in TypeScript?

If I want to define the type of a variable that will be used with setInterval in the following code snippet: this.autoSaveInterval = setInterval(function(){ if(this.car.id){ this.save(); } else{ this.create(); } ...

I'm baffled as to why TypeScript isn't throwing an error in this situation

I anticipated an error to occur in this code snippet, indicating that b.resDetails is possibly undefined, however, no such error occurred. Can someone please provide an explanation for this unexpected behavior? I'm quite perplexed. type BasicD ...

Building a personalized command-line interface (CLI) tool using Typescript

I recently created a Typescript program that converts various .json file formats. However, I realized that I have hardcoded the file path for reading. const file = readFileSync('./name_of_file_path.json', 'utf-8'); // fixed file path. f ...

The lazy loading feature in Angular 12 is not functioning correctly for path modules

My application has a jobs module with various components, and I'm trying to lazy load it. However, I've encountered an issue where accessing the module through the full path http://localhost:4200/job/artist doesn't work, but accessing it thr ...

Is TypeScript 2.8 Making Type-Safe Reducers Easier?

After reading an insightful article on improving Redux type safety with TypeScript, I decided to simplify my reducer using ReturnType<A[keyof A]> based on the typeof myActionFunction. However, when creating my action types explicitly like this: exp ...