D3 event: Latest in Type Definitions for Version 6 and Beyond

I have a collection of widgets created using d3 (version 5) and now I need to transition them to version 7. After consulting the migration guide at , I discovered the updated syntax for events:

// previously
element.on('click', (d, i, e) => ...


// now
element.on('click', (event, d) => ...

Upon switching to the new syntax, the program started running smoothly again. Great news!

The current challenge is that I am utilizing TypeScript in this project! Despite having installed the most recent @types/...

  "dependencies": {
      "d3": "^7.1.1",
         ...

  "devDependencies": {
      "@types/d3": "^7.1.0",
         ...

...I continue to encounter difficulties with type definitions and Intellisense particularly concerning events.

// 1. previous (Functioned correctly)
element.on('click', (d: MyData, i: number, e: whatever[]) => ...


// 2. adding types == Error reappears! ❌  
element.on('click', (event: PointerEvent, d: MyData) => ...


// 3. thus, my temporary solution:
element.on('click', (event: any , d: any) => ...

Interestingly, even though I have @types/d3 v7.0.1 installed, it seems like the Typings system still refers to the old v5 format. Somehow Intellisense continues to think the first parameter is data and the second is a numeric index:

https://i.sstatic.net/XelTD.png

https://i.sstatic.net/pYw7b.png

...In reality, what I receive is { event: PointerEvent, d: MyData }, as displayed in the image below.

https://i.sstatic.net/8u7HF.png

Therefore, it appears there may be an issue with D3's type declaration since Intellisense believes the Event is still in the v5 format while that is not the case in practice.

Does anyone have a solution to rectify this typing problem? It can be quite frustrating to resort to assigning "any" within my events.

Answer №1

It's common knowledge that steering clear of any like the Plague is typically the way to go, hence why you're aiming to specify a particular type! However, luck isn't on your side when it comes to the event listener's type definition. Upon inspecting the .on method's definition, you'll see that the event parameter is indeed categorized as any, enabling the broadest possible event processing:

on(typenames: string, listener: (this: GElement, event: any, d: Datum) => void, options?: any): this;

As a result, your second approach is bound to be unsuccessful, leaving the third approach as the correct resolution.

Answer №2

To tackle this issue, I implemented a new utility type called D3Event in my existing codebase. This utility type requires two type arguments:

export type D3Event<T extends Event, E extends Element> = T & { currentTarget: E }

By utilizing this utility type, I can now handle events like so:

selection.on('mouseover', (event: D3Event<MouseEvent, SVGGElement>, d: SomeType) => { ... }

Although it may add some verbosity, it enforces stricter typing compared to using any.

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

Create TypeScript declaration files dynamically within the application's memory

Is there a way to programmatically generate declaration files using TypeScript? I know we can use tsc --declaration --emitDeclarationOnly --outFile index.d.ts, but I'm not sure how to do it in code. For example: import ts from 'typescript' c ...

Switching buttons with AngularJS

I am currently working on a Github search app using the Github API in Angular. My goal is to make it so that when the user clicks the "Add to Favorite" button, the button disappears and the "Remove Favorite" button is displayed instead. I attempted to achi ...

Mastering the art of effectively capturing and incorporating error data

Is there a way to retain and add information to an Error object in typescript/javascript without losing the existing details? Currently, I handle it like this: try { // code that may throw an error } catch (e) { throw new Error(`Error while process ...

What is the classification of a function that outputs an enum element?

I am unsure about what should be the appropriate type for the function that retrieves an enum member in my code. Here is the current version of my code: interface Letter { character: string, color: Function } enum Color { Green, Yellow, ...

Prevent further selections by deactivating checkbox upon button click in Ionic framework

I am in the process of developing a new feature for my Ionic app that involves creating profile groups. Users are required to select profiles from a checkbox list, then click a button to create the group. Once created, the selected profiles should either d ...

In what situations might a finally block fail to execute?

Are there any circumstances where the code in a finally block may not be reached, aside from the usual suspects like process exit(), termination signal, or hardware failures? In this TypeScript code snippet that usually runs smoothly in node.js, occasiona ...

Identical names found in typescript within a react project

Having an issue with my react project where I am seeing a lot of duplication errors in almost all files located in this directory: C:\Users[user]\AppData\Local\Microsoft\TypeScript\4.3\node_modules@types\ I suspect ...

Testing onClick using Jest when it is not a callback function in props

I have discovered various ways to utilize mock functions in jest for spying on callback functions passed down to a component, but I have not found any information on testing a simple onClick function defined within the same component. Here is an example f ...

Exploring the relationship between two entities in Angular 7 using Typescript

Creating a Reactive form for user registration in Angular involves setting up the form data object separately from the viewmodel object. https://i.sstatic.net/ERlYa.png export interface RegisterViewModel { UserName: string; Email: string; Password: strin ...

Is there a more effective way to implement a Custom Validator using .forEach?

I have developed my own validation class as a learning exercise. Do you think this is an effective approach, or do you have suggestions for improvement? import { AbstractControl } from '@angular/forms'; export class ProjectNameValidator { pr ...

Utilizing D3 to fetch geographic data in the form of a TopoJSON file for U.S. counties

After retrieving a set of coordinates, the goal is to use D3 to find the corresponding county from a U.S. TopoJSON file. Here is an example code snippet: navigator.geolocation.getCurrentPosition(function(position) { let coordinates: [number, number] = [p ...

Tips for accessing touch events within the parent component's area in React Native

I implemented the code below in my React Native app to disable touch functionality on a specific child component. However, I encountered an issue where the touch event was not being detected within the area of the child component. How can I fix this prob ...

Issue encountered when trying to pass a string into URLSearchParams

const sortString = req.query.sort as string const params = Object.fromEntries(new URLSearchParams(sortString)) Upon moving to the implementation phase, I encountered: declare var URLSearchParams: { prototype: URLSearchParams; new(init?: string[][] ...

How can Firebase and Ionic be used to customize the password reset template for sending verification emails and more?

I'm facing an issue with firebase's auth templates not supporting my native language. Is there a way to customize the password reset template to also handle verification and email address change emails? ...

typescript push in react native is a crucial step to enhance performance and optimize

I've been diving into TypeScript within the realm of React Native. Oddly, when I translated a certain snippet to vanilla JavaScript, the application worked flawlessly. However, upon converting it back to TypeScript, an error message popped up stating ...

Here's a guide on accessing information from a local JSON file and displaying it on an HTML page using Ionic 2 with TypeScript

I have received a JSON file formatted like the following: { "records": { "patients": { "day": "Today", "details": [ { "name":"Diab", "stat":"Pending", "phno":"8197246465", "patNames":"Sandr ...

Is it possible to derive a TypeScript interface from a Mongoose schema without including the 'Document' type?

Using ts-mongoose allows me to define interfaces and schemas for my data in one place. I then export them as a mongoose schema along with the actual interface. The challenge I'm facing is finding a simple way to extract that interface without includi ...

Jest test encounters Firebase initialization error

Testing event handlers for a slack bolt app has been quite the rollercoaster. Initially, all tests passed flawlessly, making life wonderful. However, after some refactoring, the entire test suite failed to run, displaying an error indicating that firebase ...

There seems to be an issue with the touchStart and touchEnd events in Angular2 when viewed on mobile devices

The hover property in CSS is used to create interactive effects, but when trying to apply similar functionality on mobile devices using touchstart and touchend events, I am encountering issues with the responsiveness of the events. Below are the implement ...

Executing TypeORM commands yields no output

It's been a while since I last tested my Nest project with TypeORM, and now when I try to run any TypeORM command, nothing happens. I attempted to run TypeORM using these two commands: ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js ...