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

Having difficulty ensuring DayJs is accessible for all Cypress tests

Currently embarking on a new Cypress project, I find myself dealing with an application heavily focused on calendars, requiring frequent manipulations of dates. I'm facing an issue where I need to make DayJs globally available throughout the entire p ...

Is it necessary for the React generic type prop to be an extension of another type

I have recently started using TypeScript and I am facing a confusion regarding passing generic types into my higher-order component (HOC). My objective is to pass the component props as a generic type in order to have the Component with those specific type ...

The sanitizer variable becomes null when accessed outside of the NgOnInit function in Angular using TypeScript

At first, I added DomSanitizer to the component: import { DomSanitizer, SafeResourceUrl} from '@angular/platform-browser'; Next, a class was created and included in the constructor: export class BlocklyComponent implements OnInit { primar ...

How can I customize the visibility toggles for the password input field in Angular Material?

Currently immersed in the Angular 15 migration process... Today, I encountered an issue with a password input that displays two eyes the first time something is entered in the field. The HTML code for this is as follows: <mat-form-field appearance=&qu ...

I'm experiencing an issue with redirect in Nextjs that's causing an error message to appear. The error reads: "SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

I'm currently diving into the world of NextJS and working on creating a simple recipe application. Utilizing the new App Router has been smooth sailing for the most part, except for one hiccup with the login function. After successfully logging in (us ...

Using TypeScript to assign values to object properties

In myInterfaces.ts, I have defined a class that I want to export: export class SettingsObj{ lang : string; size : number; } Now I need to reference this class in another file named myConfig.ts in order to type a property value for an object called CO ...

The constant value being brought in from an internal npm package cannot be determined

I have developed an internal npm package containing shared types and constants. My project is built using TypeScript with "target": "ESNext" and "module": "NodeNext". Within one of my files, I define: export type Su ...

What methods are recommended for implementing changes in a TypeScript library throughout the development process?

When working on a TypeScript library that is utilized as a dependency by other libraries or applications, how can I efficiently handle frequent updates without going through the process of incrementing the version number, publishing it to an NPM registry, ...

Steps for accessing the camera within a custom Ionic app

Currently, I am working on a unique custom application built using Ionic and Typescript. I have encountered an issue with opening the camera to capture a picture. While my app successfully opens the native camera for capturing photos, it unfortunately tak ...

Is it possible to access the service and 'self' directly from the HTML template?

When working with Angular 6, one method to access component properties from a service is to pass 'self' to the service directly from the component. An example of this implementation is shown below: myComponent.ts public myButton; constructor(p ...

Troubleshooting a Custom Pipe Problem in Angular Material Drag and Drop

Currently, I am working on a project involving Angular Material Drag And Drop functionality. I have created a simplified example on StackBlitz which you can access through this link: here The project involves two lists - one containing pets and the other ...

Can someone provide a description for a field within typedoc documentation?

Here is the code snippet: /** * Description of the class */ export class SomeClass { /** * Description of the field */ message: string; } I have tested it on the TSDoc playground and noticed that there is a summary for the class, but not for it ...

Dealing with challenges in integrating ngx-masonry with Angular 14

I am currently working with Angular 14 framework and the ngx-masonry library (https://www.npmjs.com/package/ngx-masonry/v/14.0.1). However, I am facing some issues where it is not functioning correctly. I would appreciate any assistance or guidance on how ...

Are there any comparable features in Angular 8 to Angular 1's $filter('orderBy') function?

Just starting out with Angular and curious about the alternative for $filter('orderBy') that is used in an AngularJS controller. AngularJS example: $scope.itemsSorted = $filter('orderBy')($scope.newFilteredData, 'page_index&apos ...

Upon completion of a promise in an express middleware and breaking out of a loop, a 404 error is returned

In my efforts to retrieve an array of object (car) from express using database functions in conjunction with the stolenCarDb object, everything seems to be working fine. However, when attempting the following code snippet, it results in a 404 error w ...

What methods can I use to analyze the integrity of the data's structure?

Currently working on an API using NestJS and typeorm. I am in need of a way to verify the format of the data being returned to clients who make requests to it. For instance, when accessing the /players route, I expect the data to have a specific structure ...

What is the purpose of the tabindex in the MUI Modal component?

Struggling with integrating a modal into my project - it's refusing to close and taking up the entire screen height. On inspection, I found this troublesome code: [tabindex]: outline: none; height: 100% How can I remove height: 100% from the ...

Experiencing a compilation issue while attempting to apply the class-transformer

Encountering an issue while working with a basic example that involves class-transformer. error TS1240: Unable to resolve signature of property decorator when called as an expression. Argument of type 'ClassFieldDecoratorContext<Root, Project[]> ...

Title remains consistent | Angular 4

Struggling to change the document title on a specific route. The route is initially set with a default title. { path: 'artikel/:id/:slug', component: ArticleComponent, data: {title: 'Article', routeType: RouteType.ARTICLE, des ...

Error: 'process' is not defined in this TypeScript environment

Encountering a typescript error while setting up a new project with express+ typescript - unable to find the name 'process'https://i.stack.imgur.com/gyIq0.png package.json "dependencies": { "express": "^4.16.4", "nodemon": "^1.18.7", ...