Connect the keys from one enum to either keys or values in another enum

When working with the code below, it is important that the keys of PropertiesNamesInDataBase align with those in User.Keys. While the values of PropertiesNamesInDataBase are used in the backend, it is crucial for uniformity that the names match in the frontend.

namespace User {
    export enum Keys {
        ID = "ID",
        name = "name"
    }
}

enum PropertiesNamesInDataBase {
    ID = "id",
    name = "nm"
}

This setup poses at least two challenges:

  1. We may have to manually retype or copy-paste the keys
  2. PropertiesNamesInDataBase operates independently from User.Keys, but ideally, the keys in PropertiesNamesInDataBase should somehow reference User.Keys.

To address the second issue, one solution is to associate the keys in PropertiesNamesInDataBase with those in User.Keys:

namespace User {
    export enum Keys {
        ID = "ID",
        name = "name"
    }
}

enum PropertiesNamesInDataBase {
    [User.Keys.ID] = "id",
    [User.Keys.name] = "nm"
}

However, TypeScript does not support this approach:

Computed property names are not allowed in enums. (1164)

If you have any ideas on how to efficiently reuse enum keys or reference PropertiesNamesInDataBase's keys based on User.Keys's values, please share your suggestions.

Answer №1

If you're considering abandoning the use of enum, one alternative is to create your own enum-like objects for added flexibility. While this approach allows you to define keys only once, it does come with a trade-off – you will lose some of the built-in expressiveness that comes with using enum.

Here's an example of how you can implement this:

const KeysAndPropNames = {
  ID: { key: "ID", propName: "id" },
  name: { key: "name", propName: "nm" }
} as const;

This single object maps keys to values similar to what you had in your previous User.Keys and PropertiesNamesInDataBase enums. You can extract these enum-like objects like this:

const User = { Keys: objMapProp(KeysAndPropNames, "key") };
const PropertiesNamesInDataBase = objMapProp(KeysAndPropNames, "propName");

The function objMapProp() helps map a property access over an object:

// Library Function
function objMapProp<T extends Record<keyof T, Record<K, any>>, K extends keyof any>(
  obj: T,
  key: K
) {
  const ret = {} as { [P in keyof T]: T[P][K] };
  for (let k in obj) {
    ret[k] = obj[k][key];
  }
  return ret;
}

If you check the types of the new User and PropertiesNamesInDataBase objects using IntelliSense, you'll see they align with the old values.

To create the corresponding types named User.Keys and PropertiesNamesInDataBase, you can define them as follows:

namespace User {
  export type Keys = (typeof User.Keys)[keyof typeof User.Keys];
  // type User.Keys = "ID" | "name"
}
type PropertiesNamesInDataBase = typeof PropertiesNamesInDataBase[keyof typeof PropertiesNamesInDataBase];
// type PropertiesNamesInDataBase = "id" | "nm"

I hope this solution either fulfills your requirements or guides you on how to progress further. Best of luck!

Playground link to code

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

Switching the phone formatting from JavaScript to TypeScript

Below is the JavaScript code that I am attempting to convert to TypeScript: /** * @param {string} value The value to be formatted into a phone number * @returns {string} */ export const formatPhoneString = (value) => { const areaCode = value.substr(0 ...

Using RxJS switchMap in combination with toArray allows for seamless transformation

I'm encountering an issue with rxjs. I have a function that is supposed to: Take a list of group IDs, such as: of(['1', '2']) Fetch the list of chats for each ID Return a merged list of chats However, when it reaches the toArray ...

I can't figure out why I'm receiving undefined even though all the variables are populated with the necessary

I have been working on a project that involves implementing email and password authentication using Firebase. However, I encountered an error when the user submits their credentials: FirebaseError: Firebase: Error (auth/admin-restricted-operation). at ...

Error message encountered when trying to associate "can" with an ability instance within Types

Just copying example code from documentation import { createCanBoundTo } from '@casl/react'; import ability from './abilities'; export const Can = createCanBoundTo(ability); An error occurs on the last line: The exported variable & ...

How to anticipate an error being thrown by an observable in RxJS

Within my TypeScript application, there exists a method that produces an rxjs Observable. Under certain conditions, this method may use the throwError function: import { throwError } from 'rxjs'; // ... getSomeData(inputValue): Observable<s ...

Add a hyperlink within a button element

I am looking to add a route to my reusable 'button' component in order to navigate to another page. I attempted using the <Link> </Link> tags, but it affected my CSS and caused the 'button' to appear small. The link works if ...

Unable to utilize console.log and alert functions within the Next.js application

I'm currently facing a problem in my Next.js application where the console.log and alert functions are not functioning as intended. Despite checking the code, browser settings, and environment thoroughly, pinpointing the root cause of the issue remain ...

JavaScript: Translating Date into Moment

Is there a way to convert a Date object to Moment in JavaScript? let testDate = new Date(2020, 05, 03, 1, 2); I attempted the following code without success toMoment(testDate) What is the correct syntax to achieve this conversion? ...

Issue with blueprintjs/core type in JupyterLab Extension after running npm install

Developed a JLab extension and saved it to Git repository. Established a new environment and successfully pulled the code, which was also verified by a friend. Subsequently, included a new react object to the extension and pushed it back to Git in a fresh ...

Is there a way to reset the selected value of a specific option in Mat-Select?

Using mat-select, I need to reset the selection for a specific value of mat-select's mat-option. For instance, take a look at this example on StackBlitz In the example, the mat-select has three options; when selecting Canada, it should revert back t ...

Tips for having tsc Resolve Absolute Paths in Module Imports with baseUrl Setting

In a typescript project, imagine the following organizational structure: | package.json | tsconfig.json | \---src | app.ts | \---foobar Foo.ts Bar.ts The tsconfig.json file is set up t ...

What is the best way to delete markers from a leaflet map?

I need to remove markers from my map. I am looking to create a function that will specifically clear a marker based on its ID. I am utilizing Leaflet for the map implementation. Here is my function: public clearMarkers(): void { for (var id in this. ...

What is the reason behind TypeScript enclosing a class within an IIFE (Immediately Invoked Function

Behold the mighty TypeScript class: class Saluter { public static what(): string { return "Greater"; } public target: string; constructor(target: string) { this.target = target; } public salute(): string { ...

Implementing express-openid-connect in a TypeScript project

Trying to incorporate the express-openid-connect library for authentication backend setup with a "simple configuration," an issue arises when attempting to access the oidc object from express.Request: app.get("/", (req: express.Request, res: express.Respon ...

Encountering an error with the Next Auth adapter in TypeScript when attempting to modify the default User interface

This is my first time using TypeScript and I am attempting to customize the default User interface for next-auth. I have experimented with the following code: next-auth.d.ts import { User } from "next-auth" import { JWT } from "next-auth/j ...

Troubleshooting Angular 2: Why Array Interpolation is Failing

Greetings everyone, I am diving into Angular 2 and attempting to create a basic Todo application. Unfortunately, I've hit a roadblock. My array interpolation seems to be malfunctioning. Any assistance would be greatly appreciated. Here is my AppCompo ...

What is the best way to forward specific props from a parent to its children?

Currently, I am working on a React + Typescript architecture called "forward." The purpose of this architecture is to pass all props received down to its children components. However, I have encountered an issue where I want to restrict the type of props ...

In TypeScript, what specific term denotes a type of data?

Given the following code snippet: class Foo { } interface TypeProvider() { type(): ?; } class Bar implements TypeProvider { type(): ? { return (Foo); } } class Baz implements TypeProvider { type(): ? { return (Bar); ...

disable the button border on native-base

I'm attempting to enclose an icon within a button, like so: <Button style={styles.radioButton} onPress={() => { console.log('hdjwk'); }}> <Icon ...

Typescript, creating multiple definitions for a function with an object parameter

My dilemma lies in a function that takes an argument object and returns another object. This returned object will have a "bar" key based on the presence of the "includeBar" key as an option. I attempted to handle this scenario with different overloads: int ...