Unable to locate TypeScript declared class

I have extended a class that inherits from the EventEmmiter class.

For better support and auto-completion in IntelliSense, I wanted to display the available events to listen to. Here is my solution:

//Imports from index.ts
import {
    CommandContext,
    CommandErrorContext,
    CommandHandler
} from '../../';
import { EventEmitter } from 'events';

export class CommandHandler extends CommandHandlerEvents {

    constructor() {
        super();
    }

}

export declare class CommandHandlerEvents extends EventEmitter {
    on(event: string, listener: Function): this;
    on(event: 'failure', listener: (handler: CommandHandler, context: CommandErrorContext) => void): this;
    on(event: 'success', listener: (handler: CommandHandler, context: CommandContext) => void): this;

    once(event: string, listener: Function): this;
    once(event: 'failure', listener: (handler: CommandHandler, context: CommandErrorContext) => void): this;
    once(event: 'success', listener: (handler: CommandHandler, context: CommandContext) => void): this;

    emit(event: string, args: any[]): boolean;
    emit(event: 'failure', args: [CommandHandler, CommandErrorContext]): boolean;
    emit(event: 'success', args: [CommandHandler, CommandContext]): boolean;
}

The code above meets my requirements perfectly, but when I try to create an instance of the CommandHandler class, it throws an error:

Uncaught ReferenceError: CommandHandlerEvents is not defined

I've come across suggestions to use interfaces for the same purpose, however, switching CommandHandlerEvents from a declare class to an interface causes IntelliSense suggestions to disappear.

Here is an example of the desired outcome: image

Answer №1

By utilizing the declare keyword when defining a class or using an interface, you are incorporating elements into the type system during compile time. No additions are made during runtime. For instance, if you inspect the JavaScript output, there won't be any occurrence of CommandHandlerEvents. The purpose of the declare keyword is to inform the compiler that the specified entity will exist at runtime due to the support provided by the runtime environment where the code executes.

If your objective is to apply specific hinting for all instances of EventEmitter, then you can consider employing module augmentation to insert this type information:

import { EventEmitter } from 'events';
declare module 'events' {
  interface EventEmitter {
    on(event: string, listener: Function): this;
    on(event: 'failure', listener: (handler: EventEmitter, context: CommandErrorContext) => void): this;
    on(event: 'success', listener: (handler: EventEmitter, context: CommandContext) => void): this;

    once(event: string, listener: Function): this;
    once(event: 'failure', listener: (handler: EventEmitter, context: CommandErrorContext) => void): this;
    once(event: 'success', listener: (handler: EventEmitter, context: CommandContext) => void): this;

    emit(event: string, args: any[]): boolean;
    emit(event: 'failure', args: [EventEmitter, CommandErrorContext]): boolean;
    emit(event: 'success', args: [EventEmitter, CommandContext]): boolean;
  }
}

const eventEmitter = new EventEmitter();
eventEmitter.once(...) // receive hints

Alternatively, if you wish to create a more specialized class CommandHandler at runtime instead of simply extending EventEmitter, you can achieve that through declaration merging:

import { EventEmitter } from 'events';
export class CommandHandler extends EventEmitter { }
export interface CommandHandler {
  on(event: string, listener: Function): this;
  on(event: 'failure', listener: (handler: CommandHandler, context: CommandErrorContext) => void): this;
  on(event: 'success', listener: (handler: CommandHandler, context: CommandContext) => void): this;

  once(event: string, listener: Function): this;
  once(event: 'failure', listener: (handler: CommandHandler, context: CommandErrorContext) => void): this;
  once(event: 'success', listener: (handler: CommandHandler, context: CommandContext) => void): this;

  emit(event: string, args: any[]): boolean;
  emit(event: 'failure', args: [CommandHandler, CommandErrorContext]): boolean;
  emit(event: 'success', args: [CommandHandler, CommandContext]): boolean;
}

const commandHandler = new CommandHandler();
commandHandler.once(...) // receive hints

I trust this information is beneficial!

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

Automatically convert user input to MM/DD/YYYY format in typescript as they type the date

Hello, I am currently working on a React Native app where users input their date using TextInput. As the user types, I would like to automatically format the date as MM/DD/YYYY. Here is the function I have created so far: const formatDate(value: string ...

What is the best way to exempt a unique situation from a directive's operation?

While troubleshooting a bug related to search functionality on my page, I encountered an issue with the search component. The search feature is working correctly and returning the expected values. However, when I clear the search criteria, I noticed that t ...

Error encountered in Typescript when handling fetch options as a variable

Why does this code compile perfectly? fetch('someurl', { method: 'GET', credentials:"same-origin" }) However, the following code throws a compilation error for fetch('someurl', init); const init = { method: &apo ...

The autoimport feature is not supported by the Types Library

My latest project involves a unique library with only one export, an interface named IBasic. After publishing this library on npm and installing it in another project, I encountered an issue. When attempting to import IBasic using the auto-import feature ( ...

Tips for incorporating nested generics in Typescript

Currently, I am developing a straightforward activity execution framework that allows developers to define activities which can be executed within a workflow. To enhance type safety and boost developer productivity by utilizing type hints, I aim to incorp ...

Inserting information into an array: Access the final index consistently with TypeScript

I am interested in dynamically creating a table by allocating it, with the variable nbrBoules: boules:Boule :[] boule:Boule; Boule{id,poids} Method(){ for (var _i = 0; _i < this.nbrBoules; _i++) { this.boule.id = _i; alert(_i); this ...

Exploring the integration of PrimeNG into an Angular 4 project

I recently integrated the PrimeNG library into my Angular 4 project. Everything seems to be in place as I can see PrimeNG in my dependencies and nodemodules folder. However, when I tried to implement a simple data table using the following code: & ...

Improving the App() function in React and Typescipt

When working on my React/Typescript app, I encountered a challenge with the length of the code in one of the sections. Despite watching tutorials and searching for solutions, I couldn't find a clear way to refactor it. The specific issue is with refa ...

Redux - a method of updating state through actions

Hello, I am currently working on developing a lottery system and I have a question regarding the best approach to modify state using action payloads. Let's consider the initial state: type initialCartState = { productsFromPreviousSession: Product[ ...

Is there a way to include a query directly as a string in Drivine and Neo4j, instead of using a separate file?

My current setup involves utilizing Drivine in conjunction with Neo4j. In the provided example, there is a demonstration of injecting a query sourced from a separate file. I am curious to learn how I can directly inline a query as a string instead? ...

React Traffic Light Component: Colors Stuck After Timeout

I've been working on solving a React issue and followed a tutorial on YouTube. I'm using CodeSandbox for my project, but I'm facing a problem where the colors of the signal are not showing up and do not change after some time. I even tried u ...

Unit testing Jest for TypeScript files within a module or namespace

Recently, I've joined a mvc.net project that utilizes typescript on the frontend. There are numerous typescript files wrapped within module Foo {...}, with Foo representing the primary module or namespace. All these typescript files are transpiled in ...

Tips for managing server data and dynamically binding values in Ionic 3

I am struggling with handling data retrieved from the server. I have a provider that fetches the data through HTTP, and I want to ensure the data is loaded before the page loads. However, there is a delay in reflecting the data on the page. Can someone pro ...

Inconsistency in product returns following promise mapping - Utilizing Ionic, Angular, and Typescript

When I retrieve items from a database for a feed, it is crucial that they remain in the same order as retrieved. However, despite mapping the array from the query, the displayed feed objects end up out of sequence. Here's the snippet of code: let ...

Disabling ESLint errors is not possible within a React environment

I encountered an eslint error while attempting to commit the branch 147:14 error Expected an assignment or function call and instead saw an expression @typescript-eslint/no-unused-expressions I'm struggling to identify the issue in the code, even ...

Attempting to utilize Array Methods with an Array Union Type

Currently, I am in the process of refactoring an Angular application to enable strict typing. One issue I have encountered is using array methods with an array union type in our LookupService. When attempting to call const lookup = lookupConfig.find(l =&g ...

The 'MutableRefObject<null>' type is lacking the following properties that are present in the 'Element' type

I'm eager to implement intersection observer in my React Typescript project. (https://www.npmjs.com/package/react-intersection-observer) However, I encountered an issue with setting the root: const root = useRef(null); const { ref, inView, entry } ...

What could be causing the ERROR TypeError in an Angular form where "_co.service.formData" is undefined?

My attempt to create a form in Angular 7 has resulted in an error message: ERROR TypeError: "_co.service.formData is undefined" Here is the HTML code for the component: <form (sumbit)="signUp(form)" autocomplete="off" #form="ngForm"> <div clas ...

NextJs 13 unveils its cutting-edge dynamic sitemap feature

I am currently working on implementing a dynamic sitemap for NextJs 13.4.6, referring to the guide available at . However, I have encountered an issue with the code provided towards the end of the article which is supposed to generate a sitemap for NextJS ...

Error encountered in Nest.js tests due to dependency injection issues between modules. The module 'src/foo/foo.module' cannot be located from 'bar/bar.service.spec.ts'

Encountering an error message Cannot find module 'src/foo/foo.module' from 'bar/bar.service.spec.ts' while testing a service that relies on another module. I am facing difficulty in setting up the test scenario for a Nest.js project wi ...