Assigning string properties to different types

I have numerous data types, each with a common property called dataType, and I am currently mapping each one to that specific value:

interface GroupData {
    dataType: "group";
    name: string;
    people: PersonData[];
}

interface PersonData {
    dataType: "person";
    name: string;
    email: string;
    messages: MessageData[];
}

interface MessageData {
    dataType: "message";
    message: string;
    timestamp: number;
}

interface DataTypeMap {
    group: GroupData;
    person: PersonData;
    message: MessageData;
}

This method works for now, but it's quite manual. In my application, I deal with a large number of data types which tend to change frequently. I want to streamline this process by automating it further. Here's what I've attempted so far:

type DataType = GroupData
    | PersonData
    | MessageData;

type DataTypeMap = {
    [(T in DataType)["dataType"]]: T;
};

Handling a single union of data types is simpler compared to mapping keys based on values, however, TypeScript does not support this approach. The following TS errors are popping up:

A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
Cannot find name 'T'.
'DataType' only refers to a type, but is being used as a value here.

From what I can gather, these issues stem from syntax errors. It seems like using in with unions other than strings and applying bracket selectors in an index signature may be problematic.

Is there a way to map a collection of data types based on a shared property?

Answer №1

You're almost there! Here's the breakdown:

type DataMapTypes = {
    [T in DataTypes['dataType']]: Extract<DataTypes, {dataType: T}>;
};

DataTypes represents a combination of all type interfaces. DataTypes['dataType'] is a collection of string literals for type names.

In our mapping, we designate the keys as these string names. For each key, we aim to match it with the respective interface. We utilize Extract to filter out only those union members that can contain {dataType: T}.

This results in:

type DataMapTypes = {
    group: GroupData;
    person: PersonData;
    message: MessageData;
}

Check out the Typescript Playground demo here

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

Implementing advanced error handling using custom error messages with enums

I'm trying to use Zod to validate a gender field with z.nativeEnum(), but for some reason my custom error messages are not being applied: gender: z.nativeEnum(Gender, { invalid_type_error: 'Le sexe doit être homme ou femme.', ...

Transform a Typescript type that includes multiple string options into an array containing those options as values

Sending Status: const statusArray = ["confirmed", "pending", "canceled"] Purpose: While the type is automatically generated, I also require it to be in array form. ...

Struggling to create a TypeScript definition file - the JSX element 'SideMenu' lacks any construct or call signatures

I am currently working on creating a type definition file for react-native-side-menu in order to properly declare it. I have integrated it into a TypeScript project, but unfortunately, there are no TypeScript definitions available. Normally, my approach i ...

Reasons why a functional component may not trigger a rerender after a state change using useReducer()

When using react Hooks, specifically useReducer, I found that although the state changes, the functional component does not rerender. Additionally, when trying to open the drawer by pressing a button in the menu, even though the state changes the drawer re ...

What is the best way to utilize namespaces across multiple files in your program

I am currently working with TypeScript 1.6.2 and atom-typescript. In my project, I'm attempting to utilize namespaces across separate files: // Main.ts import * as _ from 'lodash' namespace Test { export var value = true } // Another.ts ...

Mastering Two-Way Binding in Angular 2 with JavaScript Date Objects

I am currently utilizing Angular 2 and have encountered the following code: Within the JS file, this code initializes the employee-variable for the template: handleEmployee(employee : Employee){ this.employee = employee; this.employee.sta ...

Alter the style type of a Next.js element dynamically

I am currently working on dynamically changing the color of an element based on the result of a function //Sample function if ("123".includes("5")) { color = "boldOrange" } else { let color = "boldGreen" } Within my CSS, I have two clas ...

Struggling with TypeScript errors when using Vue in combination with Parcel?

While running a demo using vue + TypeScript with Parcel, I encountered an error in the browser after successfully bootstrapping: vue.runtime.esm.js:7878 Uncaught TypeError: Cannot read property 'split' of undefined at Object.exports.install ...

Activate function on Ctrl + K in a React TypeScript project

I am currently developing a React TypeScript application using version v18.2.0. My goal is to trigger a function when the user simultaneously presses Ctrl + K. Here is the code snippet within my component: const keyDownHandler = (event: KeyboardEvent) =& ...

Jest encountering errors when compiling a generic function

I'm able to successfully run my Node app, but running tests on a class with Generics is causing an error. The test code looks like this: import { Request, Response } from 'express'; import { JsonWebTokenError } from 'jsonwebtoken' ...

Convert C# delegate into TypeScript

Sample C# code snippet: enum myEnum { aa = 0, bb, cc, } public delegate void MyDelegate(myEnum _myEnum, params object[] _params); public Dictionary<myEnum , MyDelegate> dicMyDelegate = new Dictionary<myEnum , MyDelegate>(); publi ...

What sets apart the utilization of add versus finalize in rxjs?

It appears that both of these code snippets achieve the same outcome: Add this.test$.pipe(take(1)).subscribe().add(() => console.log('added')); Finalize this.test$.pipe(take(1), finalize(() => console.log('finalized'))).sub ...

Undefined value is returned for Vue 3 object property

Is there a way to extract additional attributes from the Keycloak object ? Currently, If I try, console.log(keycloak) it will display the entire keycloak object. Even after reloading, it remains in the console. However, when I do, console.log(keycloak.t ...

Nestjs struggles with resolving dependencies

Having trouble finding the issue in my code. (I'm still new to nestjs and trying to learn by working on some apps). The console log is showing the following error: Nest can't resolve dependencies of the UrlsAfipService (?). Please ensure tha ...

invoking a function within an object in Typescript

export class MockedDataService { constructor(private Session: SessionService) {} private getMockedResponse(name:string){ return ""; // placeholder for the response data, will be a promise } public mocked:{ products:{ ...

Issue: Unable to resolve all parameters for LoginComponent while implementing Nebular OAuth2Description: An error has occurred when attempting to

I have been attempting to utilize nebular oauth in my login component, following the documentation closely. The only difference is that I am extending the nebular login component. However, when implementing this code, I encounter an error. export class Lo ...

Is it possible to set up an automatic redirection to the Identity Provider sign-in page when accessing a protected page in Next.js using Auth.js?

Currently in the process of developing a web platform utilizing [email protected] and Auth.js([email protected]). The provider has been configured with the given code, allowing successful signing in using the "Sign in" button. auth.ts import Ne ...

After utilizing the d3-scale function to declare an object, my developer visual suddenly ceases to function

Upon completing a section of a Power BI tutorial, the developer encountered a visual that displayed nothing but a blank page (despite running correctly). Unable to pinpoint the issue, debugging was initiated. The following test code snippet for debugging w ...

Discovering and Implementing Background Color Adjustments for Recently Modified or Added Rows with Errors or Blank Cells in a dx-data-grid

What is the process for detecting and applying background color changes to the most recently added or edited row in a dx-data-grid for Angular TS if incorrect data is entered in a cell or if there are empty cells? <dx-data-grid [dataSource]="data ...

Upon updating my application from Angular 14 to 16, I encountered an overwhelming number of errors within the npm packages I had incorporated

After upgrading my angular application from v14 to v16, I encountered numerous peer dependencies issues, which led me to use the --force flag for the upgrade process. However, upon compiling, I am now faced with a multitude of errors as depicted in the scr ...