exporting an enum from a typescript type definition file

As I compile the type definitions for a library that I'm utilizing, I came across one function that identifies the mouse button clicked by an integer:

 //index.d.ts
 export as namespace myLib;
 // activates the library listening for a specific mouse button
 function activate(button : number ) : void 

To enhance readability, I introduced an enum:

//index.d.ts
export as namespace myLib;
export enum MouseButton {
    LEFT = 1,
    MIDDLE = 2,
    RIGHT = 4
}

export function activate(button : MouseButton ) : void;

Upon importing and using this function, everything compiles successfully. However, during execution in the browser, the enum seems to be stripped away, resulting in the error message

Cannot read property 'LEFT' of undefined
.

In an attempt to resolve this issue, I restructured the files as follows:

//MouseButton.ts
export enum MouseButton {
    LEFT = 1,
    MIDDLE = 2,
    RIGHT = 4
}

//index.d.ts
export as namespace myLib;
import {MouseButton} from MouseButton;
export {MouseButton} from MouseButton;
export function activate(button : MouseButton ) : void;

Now, I can use

import {MouseButton} from "myLib/MouseButton"; import * as myLib from "myLib"
. Nonetheless, this solution necessitates two imports. Although referencing myLib.MouseButton still compiles, it does not run as intended.

Is there a way to import and reference the MouseButton enum through the myLib imported via import * as myLib? I am seeking an explanation not only on how to achieve this but also on why my initial solution failed or if such an approach is unfeasible. Any pointers to resources elucidating these issues would be highly appreciated.

PS: I also experimented with the syntax recommended here re-export Typescript enum from namespace?, yet it did not yield the desired outcome.

PPS: The module under consideration is a UMD module from the cornerstone project (https://github.com/cornerstonejs/cornerstone) incorporated into an angular 6 project.

Answer №1

(Adding onto t.animal's response)

Creating declaration files can be quite challenging, as explained in detail in the extensive documentation. Sometimes examining existing .d.ts files can provide assistance.

When it comes to enum, defining them as const enum is a straightforward and neat approach. This method is used for libraries like jquery, as demonstrated in @types/jquery/index.d.ts for Mouse and Key. The advantage of using const enum is that its members are compiled directly as values, unlike standard enums which are compiled as arrays; you can experiment with this distinction on the TypeScript Playground.

Answer №2

Thanks to the helpful comment from Romain Denau, I was able to solve my issue. His suggestion pointed me in the right direction by highlighting how the TypeScript compiler generates code from an enum declaration. By declaring the enum as const, the compiler can replace the identifier with its corresponding value, essentially inline it and preventing any leakage of the enum into the production code. This approach has been very effective for me!

//index.d.ts
export as namespace myLib;

export const enum MouseButton {
    LEFT = 1,
    MIDDLE = 2,
    RIGHT = 4
}

export function activate(button : MouseButton ) : void;

Answer №3

After conducting some brief research on the subject, I came across a noteworthy point regarding exporting enums from a type definition file using export enum const. This method is considered to be suboptimal because it requires enabling the --isolatedModules flag, which might not be feasible in certain environments such as create-react-app, leading to potential complications.

Instead of that approach, I opted for a more conventional syntax in my shared.d.ts file:

  export enum EReviewStatus {
    PENDING = 'PENDING',
    SENT = 'SENT'
  }

Subsequently, I have a separate .js file that is imported into the main block of the package.json like so:

"main": "shared.js",

In this setup, leveraging CommonJS exports to ensure compatibility with both Node.js and the frontend, I include:

module.exports.EReviewStatus = {
  PENDING: 'PENDING',
  SENT: 'SENT'
}

This methodology has proven effective and is generally regarded as a better practice since it promotes clear separation between your code and type definitions.

Answer №4

In order to export an enum from a .d.ts file, you will need to create a separate file such as constants.ts and export the enum from there instead. This is because enums are treated more like variables rather than types or interfaces.
I hope this solution proves helpful! 😊😊😊😊

Answer №5

I'm taking a similar approach as @TeemuK:

// Creating a constant for exporting
export const ReviewStatusEnum {
    PENDING = 'PENDING',
    SENT = 'SENT'
} as const

// Using inferred valid values for typing
export type ReviewStatusType = keyof typeof ReviewStatusEnum

By doing this, you can avoid duplicating your enum values.

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

Only JSON objects with a boolean value of true will be returned

I am working on returning JSON objects in JavaScript/TypeScript that have a true boolean value for the "team" property. For example, the JSON data I am using is as follows: { "state": "Texas", "stateId": 1, "team": true }, { "state": "Cali ...

combineLatest will trigger only for the initial event

I am looking to combine 3 events and trigger a service call when any of them are fired. Currently, I am using the combineLatest method, but it seems to only work when the first event is triggered by filterChanged. The issue here is that filterChanged is a ...

Obtain a union type using the `keyof typeof` syntax

Is there a way to retrieve the union or enum type from a typeof type in TypeScript? For instance: const myConfs: { [k: string]: (myArg: { name: string }) => string } = { 'Hello': ({ name }) => `World from ${name}`, 'Goodbye': ...

Error: Unable to execute fields.map function while generating a dynamic sitemap using next-sitemap module

I'm in the process of creating a dynamic sitemap for my website and here's the code I'm using: import { GetServerSideProps } from 'next'; import { getServerSideSitemap, ISitemapField } from 'next-sitemap'; import { makeSl ...

Incorporating dynamic dependency injection in Angular 2 through the use of @Input()

Let's consider a scenario where an Angular 2 component-directive needs to dynamically determine the injected dependency it uses based on an @Input(). For example, I would like to be able to specify <trendy-directive use="'serviceA'"> ...

I am having trouble getting the guide for setting up a NextJS app with Typescript to function properly

For some time now, I have been experimenting with integrating Typescript into my NextJS projects. Initially, I believed that getting started with Typescript would be the most challenging part, but it turns out that installing it is proving to be even more ...

How to dynamically assign a type based on a single choice from multiple options (props)

I have a props object that includes: { option1, option2, option3, option4, general, otherProps } The requirement is to allow only one option to be used at a time. Here are the types defined: interface MyTypes { option1: boolean option2: boolean option3 ...

Using TypeScript along with the "this" parameter

Hi there, I'm encountering an issue with the code snippet below. It keeps throwing an error message that says "Property 'weatherData' does not exist on type 'XMLHttpRequest'." The purpose of this code is to display weather informat ...

String Compression - Number of Elements

Suppose I define a specific type: type SomeType = 'a' | 'b' | 'c' Is there a TypeScript function available that can calculate the number of unique values a variable of type SomeType can hold? assertEq(countUniqueValues(SomeTy ...

An array becomes undefined once the previous array is removed

Consider the following code snippet: using the splice method, a specific item from Array1 is retrieved and stored in a variable called Popped. Next, Popped is added to array2. However, if we then delete the value from Popped, why does array2 become undef ...

At what point do we employ providers within Angular 2?

In the Angular 2 documentation, they provide examples that also use HTTP for communication. import { HTTP_PROVIDERS } from '@angular/http'; import { HeroService } from './hero.service'; @Component({ selector: 'my-toh&ap ...

Developer tools indicate React state property is set despite it always being undefined

Encountering a perplexing problem while using ReactJs along with TyperScript. In the constructor of the component, I initialize the state with a value from the provided props: constructor(props: IEditProps) { super(props); const initialState = { ...

Can the type definition be shared between React and AWS CDK when using Node.js?

I am currently building an application with React frontend and AWS CDK backend, using TypeScript. Due to the usage of GraphQL in certain parts of the application, I am finding myself duplicating type definitions extensively. For instance, when creating a ...

Different results are being obtained when destructuring props in a component

Just diving into the world of React and trying to grasp destructuring. I've been doing some reading on it, but I'm currently stuck. When I try to destructure like this function MList({action}) { // const data = [action];}, I only get 'camera ...

What is the process for incorporating a third-party library into Angular 6?

Many developers face the challenge of using external libraries in Angular that are not officially supported, such as Clappr and HashWords. The desire is to integrate these libraries seamlessly into an Angular project, almost treating them like native Ang ...

What is the best method to retrieve the value of a cell in a different cell within the same row in an Angular Material Data-Table?

I am working with an Angular Material Data Table that has four columns. In every row, the last cell contains a button with an on-click function attached to it. I need to pass the value from the first cell ("Name") as a parameter in the corresponding button ...

Unable to utilize `request.on` event listeners for terminating stream requests in NextJS

Currently, I am in the process of developing an API endpoint that streams data in order to provide live updates to components based on database events. While I have made significant progress in getting everything to function correctly, I have encountered a ...

Getting Form Value in Component.ts with Angular 5

How can I incorporate an input form into my component while constructing a form? <div class="row"> <div class="col-md-6 offset-md-3 text-center> <h2> Login Form </h2> <form (ngSubmit)="OnSubmit(login.value,password.value)" #l ...

Encountered an issue loading resource: net::ERR_BLOCKED_BY_CLIENT while attempting to access NuxtJS API

After deploying my NuxtJS 2 app on Vercel and adding serverMiddleware to include an api folder in the nuxt.config.js file, everything was working smoothly. However, when I tried making an api call on my preview environment, I encountered an error: POST htt ...

What is the proper way to indicate the pointer to the current element within the array?

How can I modify a code that displays a list of posts? import React from "react"; type respX = { "id": any, "userId": any, "title": any, "body": any, } interface PropsI { } interface StateI { data: respX []; } export class Compone ...