A more efficient method for defining and utilizing string enums in Typescript

 enum PAGES {
  HOME = 'HOME',
  CONTACT = 'CONTACT',
}

export const links: { [key: string]: string } = {
  [PAGES.HOME]: '/home',
  [PAGES.CONTACT]: '/contact',
};

export function getLink(page: string) {
  return BASE_URL + links[page];
}

Is there a more efficient way to define the enum constants without repeating the string values?

I noticed that my code has redundant strings in defining the enums.

Exploring the use of mapped types:

 type PAGE_KEY = 'HOME' | 'CONTACT';

export const urls: { [key: string]: string } = {
  HOME: '/home-page',
  CONTACT: '/contact-us/?version=v2',
};

export function getLink(page: PAGE_KEY) {
  return BASE_URL + urls[page];
}

Answer №1

To avoid repetition in this scenario, it is essential to derive your types from your values while utilizing type inference. Each JavaScript expression corresponds to a TypeScript type. As noted by Bergi, we can determine the type of a value using the typeof operator in a type context. By combining this with the keyof type operator, we can create a union type that includes all property keys within the urls object.

export const urls = {
  REQUEST_OTP: '/v1/auth/request-otp',
  LOGIN: '/v1/auth/login/?version=v2'
};

export type RouteKey = keyof typeof urls;

export function getUrl(route: RouteKey) {
  return BASE_URL + urls[route];
}

Playground Link

In the above example, we utilized the typeof operator to establish the type of the urls object as follows:

{
  REQUEST_OTP: string,
  LOGIN: string
}

We then used the keyof operator to generate a union type comprising the property keys of that type, which are:

'REQUEST_OTP' | 'LOGIN'

It's worth noting that the variable urls does not have an explicit type annotation. Leveraging type inference not only reduces verbosity but also yields a more robust type than { [key: string]: string }.

Alternatively, we could forego declaring the type alias RouteKey and simply define the function like this:

export function getUrl(route: keyof typeof urls) {
  return BASE_URL + urls[route];
}

Answer №2

It's important to provide specific details about what aspects of your current sample need improvement in order to determine if this alternative solution is better tailored to your needs. Here is a revised version of the code snippet:


type RouteKey = 'request-otp' | 'login';


export const urls: { [key: RouteKey]: string } = {
  'request-otp': '/v1/auth/otp',
  'login:': '/v1/auth/login',
};


export function getUrl(route: RouteKey) {
  return BASE_URL + urls[route];
}

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

What is the best way to declare a global TypeScript variable in a definition file to make it accessible for import?

My issue revolves around an external JS library that contains a global parameter: function Thing() { ... } ... var thing = new Thing(); I have a TypeScript definition file named thing.d.ts with the following content: declare var thing: ThingStatic; ex ...

Access the most up-to-date information through the API URL

Objective: Whenever the 'Test' Button is clicked, new data must be fetched from the backend using the API link and displayed on the modal form. Issue: If text in the input box is changed or deleted, then the modal is closed and the 'Tes ...

Struggling to incorporate method decorators to handle http errors in Angular?

My goal is to implement error handling for all http requests using custom decorators. Here's my current code snippet: createRecord(data: data) { return this.httpClient.post(`${this.apiURL}/record/`, data); } I am looking to refactor thes ...

Angular sets the required property only when the button is clicked

Is there a way to make a field required in Angular only when a button is clicked? Currently, the error message appears even before the user interacts with the field. I would like the error message "folder name is required" to only appear when the user cli ...

Application of Criteria for Zod Depending on Data Stored in Array Field

I am currently working on an Express route that requires validation of the request body using Zod. The challenge arises when I need to conditionally require certain fields based on the values in the "channels" field, which is an array of enums. While my cu ...

Dealing with circular dependencies in NestJS by using ForwardRef

Hey everyone, I've been running into a circular dependency issue with NestJS. I tried using the forwardref method, but it hasn't resolved the problem for me. // AuthModule @Module({ imports: [ forwardRef(() => UserModule), JwtModule ...

What is the best way to prevent the hassle of manually reloading a VS Code extension each time I make updates

While working on my VS Code extension, I keep encountering the issue of opening a new instance of VS Code every time I run the extension to view recent changes. This becomes especially tedious when using VS Code remote and having to enter my password twice ...

Asynchronous jQuery operations using promises and finally functionality

I am attempting to interact with a REST api using jQuery's ajax feature. My goal is to return the Promise<Customer> object, but I am encountering an error stating that the property finally is missing. It used to work before, so I assume there h ...

When using the ionic 3 storage.get function, it may return a null value when accessed outside

In regards to storage, the function is returning a null value outside of the function. Below is the code snippet: username:any; this.storage.get('user').then((value) => { this.username = value; }); console.log(this.username); Ou ...

Mastering Typing for Enhanced Order Components using Recompose and TypeScript

I have been working on integrating recompose into my react codebase. As part of this process, I have been experimenting with getting some basic functionality to work. While I have made progress, I am uncertain if I am following the correct approach for usi ...

The function onClick in Chart.js allows for passing the selected object in Typescript

In the documentation for Chart.js, I found a reference to an onClick function that is triggered whenever a click event occurs on the chart. The code snippet provided looks like this: options: { onClick: this.Function } Function(event, array){ ... } ...

Unable to proceed due to lint errors; after conducting research, the issue still remains

I'm still getting the hang of tslint and typescript. The error I'm encountering has me stumped. Can someone guide me on resolving it? I've searched extensively but haven't been able to find a solution. Sharing my code snippet below. (n ...

Transform the `PascalCase` format into `strictCamelCase` in TypeScript type conversion

By utilizing the built-in Uncapitalize<S> function, you can easily convert a string like FooBar to fooBar: const fooBar: Uncapitalize<'FooBar'> = 'fooBar'; However, this method proves inadequate when dealing with class name ...

Simplify typing in TypeScript using default generic parameters

Imagine I came across the following object: const inquiries = { whoCreatesIssues: { options: { sameTeam: { id: 'SAME_TEAM' }, management: { id: 'MANAGEMENT' ...

Menu with options labeled using IDs in FluentUI/react-northstar

I'm currently working on creating a dropdown menu using the FluentUI/react-northstar Dropdown component. The issue I'm facing is that the 'items' prop for this component only accepts a 'string[]' for the names to be displayed ...

Exploring the contrast of && and ?? in JavaScript

My current focus is on utilizing the Logical AND && and Nullish coalescing operator ?? in handling conditional rendering of variables and values. However, I find myself struggling to fully comprehend how these operators function. I am seeking clar ...

Different ways to separate an axios call into a distinct method with vuex and typescript

I have been working on organizing my code in Vuex actions to improve readability and efficiency. Specifically, I want to extract the axios call into its own method, but I haven't been successful so far. Below is a snippet of my code: async updateProf ...

Tips for sending data to CSS in Angular

I have an Angular application where I need to calculate the width of an element and store it in a variable called finalposition. Then, I want to move this element to the left by (finalposition)px when hovering over it. How can I achieve this styling effect ...

Invoking a functionality within a stream of events through an observable's subscribe

Service2.ts public flags$: BehaviorSubject<FlagName> = new BehaviorSubject<FlagName>("custom-flag-1"); This flag is set up as follows: private _setFlags = () => { const flagsData = this._customClient.getFlags(); if (f ...