Using generics to assign specific attributes within an object

Considering the given categories:

type Category1 = {
  label: 'category1';
  attribute: string;
};

type Category2 = {
  label: 'category2';
  value: string;
};

type Category3 = {
  label: 'category3';
  attribute: number;
};

The objective is to manually construct an object with the following structure:

{
  category1: {
    key: 'attribute'
  },
  category2: {
    key: 'value'
  }, 
  category3: {
    key: 'attribute'
  }
}

The intention is to define it in a way that automatically recognizes the allowed top-level property names (the "label" value from each type) along with the potential values for key (any property names in that type besides "label" are valid).

This can be achieved for one type as shown below:

type AllCategories = Category1 | Category2 | Category3;

type CustomObject<T extends AllCategories> = {
  [Property in T['label']]: {
    key: keyof Omit<T, 'label'>;
  };
};

const customizedObj: CustomObject<Category1> = {
  category1: {
    key: 'attribute',
  },
};

This type will permit any individual ABC type. Yet, the challenge lies in enabling the object to encompass all ABC types.

The aim is to specify "category1", and when assigning its "key" value, only "attribute" should be accepted. Subsequently, adding the "category2" key to the same object must restrict the possible "key" value to just "value".

The mentioned types serve as examples; actual ones comprise numerous fields and diverse types.

Answer №1

To iterate over each member of your input union, you can make use of key remapping in mapped types. Here's an example:

type MyObject<T extends { name: string }> = {
  [U in T as U['name']]: { pk: Exclude<keyof U, "name"> }
};

For A | B | C, the output would be:

type M = MyObject<A | B | C>;
/* type M = {
    a: {
        pk: "id";
    };
    b: {
        pk: "url";
    };
    c: {
        pk: "id";
    };
} */

Link to Playground for code execution

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

Ensuring Safe Data Storage for an Angular 2 Project with Local Storage

One thing that worries me is the possibility of a hacker accessing the developer's console or local storage to alter user data, like the company name, and then gaining unauthorized access to my database. Here's a closer look at the issue: Curren ...

There is an issue with the hook call while trying to establish a context with a reducer

I am facing an issue while setting up the AppProvider component that utilizes a context and reducer to manage global data for my application. The problem seems to be arising from the useReducer hook used within the AppProvider. I have checked the error mes ...

Utilizing variables to set the templateUrl in Angular2

Trying to assign a variable to the templateUrl in my component, but it's not functioning as expected. @Component({ selector: 'article', templateUrl: '{{article.html}}', styleUrls: ['styles/stylesheets/article.comp ...

Creating a Custom Select Option Component with Ant Design Library

Is it possible to customize options in an antd select component? I have been trying to render checkboxes alongside each option, but I am only seeing the default options. Below are my 'CustomSelect' and 'CustomOption' components: // Cu ...

Issue with RxDB: Collection not found upon reload

Exploring the integration of RxDB in my Angular project. I wanted to start with a simple example: export const LANG = { version: 0, title: "Language Key", type: "object", properties: { key: { type: "string", primary: true } }, requ ...

"Alert in Javascript executing prematurely prior to initiating the function for sending a get request

private validateURL(url: string) { let isValid = false; this.$http.get(url).then( (data) => { console.log('success'); isValid = true; } ).catch( (reason) => { console. ...

Angular: Utilizing httpClient to retrieve an object map and passing it as a return value in a function

I have a basic Angular application that retrieves data from a Spring-Boot backend. export class UserDto { constructor( public login: string, public password: string, ) { } } export class AuthService { private url = '....'; get ...

Remove any div elements that do not contain any content

I have a method on my front end that receives HTML as a string from the backend Here is the code snippet: private async tryGetOooMessage(employeeId: string): Promise<string> { try { return await firstValueFrom(this.messages.getOutOfOfficeI ...

Retrieving display format or formatted value from an object with Moment.js

I am currently working on a project using Angular and Material2. Within this project, I have created a moment object in the following way: myDate = moment.utc(new Date()).format("YYYY-MM-DD HH:mm:ss"); This object is then passed as an argument to ano ...

The deployment of the Next.js project encountered issues due to TypeScript types

Currently, I am in the process of deploying my project using Vercel. The project was built using Next.js and TypeScript. I have integrated Next-auth with the credentials provider for authentication. By default, this authentication package includes an obje ...

Do you know of a more efficient way to write Typescript class and interface definitions?

In my TypeScript project, I'm creating a class with constructor parameters defined by an interface to limit the properties to only those that are specified. Although the current code snippet achieves the desired functionality, I am looking for a way ...

extracting the properties of a generic type to retrieve a specific object's attribute

Is it possible to destructure a generic lambda function parameter recursively to check if a property exists within an object? I want to keep the input types of this function as general as possible without extending T to any existing type. Let's clari ...

Having difficulty refreshing UI using React useState while trying to update an array of elements

Struggling with updating my UI using React and useState. Any help would be greatly appreciated. I am trying to remove an item that a user added. interface Links { link: string; } const [redirectLinks, setRedirectLinks] = useState<Links[]>([ { ...

What is the process of asynchronously importing a module's exported function using dynamic imports and then executing it?

When working with asynchronous callbacks in a promise promise.then(async callbackResultValue => { //here }) I experimented with this code: const browserd = await import('browser-detect'); if (typeof browserd === 'function') { ...

Error: The JSON file cannot be located by the @rollup/plugin-typescript plugin

I have recently set up a Svelte project and decided to leverage JSON files for the Svelte i18n package. However, I am facing challenges when trying to import a JSON file. Although the necessary package is installed, I can't figure out why the Typescri ...

What is the reason behind TypeScript expecting 'never' as a function argument when retrieving the function type using generics?

I need some assistance with transitioning from TS 2.6 to 3.4 as I am encountering unexpected issues. Previously, my code was functioning correctly, but now I am facing a compiler error: type MyNumberType = 'never' | 'gonna'; type MyStri ...

Verify that each field in the form contains a distinct value

I have a formarray with nested formgroups. How do I ensure that the elements within each formgroup are unique? Here is an example of my form setup: form: FormGroup = this.formBuilder.group({ fields: this.formBuilder.array([]), }); private createField() ...

Fetching data from React Router v6 Navigate

When I navigate to a new route, I am encountering an issue with passing state data in TypeScript. The error message says: Property 'email' does not exist on type 'State'." The parent functional component looks like this: naviga ...

Discover which references are yet to be resolved within a tsx file

I have been tasked with developing a custom builder for a web application. The challenge now is to automatically detect imports in the code so that the right modules can be imported. My current solution involves traversing the AST of the scripts, keeping ...

"Exploring the world of 3rd party libraries in Angular2 with Typescript and Webpack

I've begun working on a fantastic seed project that can be found at: https://github.com/AngularClass/angular2-webpack-starter However, I've encountered an issue with integrating third-party modules. Can anyone offer guidance on how to properly a ...