Associate enumeration values with distinct data types within TypeScript

My TypeScript code snippet looks like this:

enum EventType {
  EVENT_A = 'eventA',
  EVENT_B = 'eventB',
  ... // more event types
}

interface Event {
  type: EventType;
}

interface EventA extends Event {
  type: EventType.EVENT_A;
  data: PayloadForEventA;
}

interface EventB extends Event {
  type: EventType.EVENT_B;
  data: PayloadForEventB;
  id: number;
}

... // More Event interfaces

I am wondering if it is possible to map the values of EventType to corresponding interfaces. If automatic mapping is not feasible, can I manually specify the types mapped by the enum values?

I am aware that values can be mapped to types as shown in this question. By using the method demonstrated below, a lookup table can be created:

type EventTypeLut = {
  'eventA': EventA,
  'eventB': EventB,
  // ...
};

However, hardcoding the enum value into the LUT may cause maintenance issues if the enum value changes in the future (something beyond my control).

When attempting to use EventType.EVENT_A as a key name, TypeScript throws an error with "property or signature expected". Even trying template strings does not seem to work. It appears that computed key names, even if constant expressions like 1+2, are not allowed.

The reason for my attempt is to create a typed EventEmitter where the enum value of EventType serves as the name and the respective typed object for the callback function.

If there is a better approach to achieve this, please provide some guidance. Thank you in advance.

Answer №1

Another suggestion to @chharvey 's response is to verify that all of the EventType keys are present in the EventTypeLut by using this code snippet:

type EventTypeLut = {
  [T in EventType]: {
    [EventType.EVENT_A]: EventA,
    [EventType.EVENT_B]: EventB,
  }[T]
};

If any enum members are missing, TypeScript will raise an error with the [T in Event].

Answer №2

When it comes to object literals, interfaces, and object types, computed keys are a useful feature. Take this example:

const obj = {
  [2 + 2]: 'four'
};
obj[2 + 2] === 'four'; // true
obj[1 + 3] === 'four'; // true
obj[4]     === 'four'; // true
obj['4']   === 'four'; // true

Computed keys allow for expressions enclosed in brackets to be utilized as keys within an object literal, interface, or object type declaration. Why not experiment with computed keys in your EventTypeLut object type like so:

type EventTypeLut = {
  [EventType.EVENT_A]: EventA,
  [EventType.EVENT_B]: EventB,
  // ...
};

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

Updating row values in an Angular table

I have a reusable table with the [cellData]="row" attribute to populate each cell on the table (see sample table in the screenshot). My question is, how can we replace the null values on the template with "---" so that instead of displ ...

When attempting to utilize the Angular2 http.get function to retrieve data from a Restful Webservice, I encountered an issue where the error status 200 was returned

Angular 2 Issue with http.get Request to Restful Webservice When I try jsontest.com, I receive the value properly. getCurrentTime() { //return this.http.get('http://date.jsontest.com') return this.http.get('http://localhost:80 ...

Merge arrays values with Object.assign function

I have a function that returns an object where the keys are strings and the values are arrays of strings: {"myType1": ["123"]} What I want to do is merge all the results it's returning. For example, if I have: {"myType1": ["123"]} {"myType2": ["45 ...

Steer clear of chaining multiple subscriptions in RXJS to improve code

I have some code that I am trying to optimize: someService.subscribeToChanges().subscribe(value => { const newValue = someArray.find(val => val.id === value.id) if (newValue) { if (value.status === 'someStatus') { ...

After the click event, the variable in the Angular .ts file does not get refreshed

Great! I have a service in my .ts component that loops through an array of court names. Every time I click on a next or back arrow event, a counter is incremented starting at 0, where index 0 corresponds to field 1 and so on. The issue I'm facing is ...

Updating a separate component in Next.js upon the deletion of an item from the Supabase database

I am facing an issue with updating my parent component after deleting an item from the database. To fetch items from the database, I use a simple approach: const filter = useFilter((query) => query.eq("createDate", date), [date]); const [{ ...

Ways to activate auto completion without using a string

Can anyone assist us with the tinymce editor? We have implemented an auto completion feature using a plugin from TinyMCE's documentation, but we are having trouble changing the triggering behavior. Currently, it only suggests options when "@" is typed ...

MyApp is encountering issues resolving all parameters

I'm encountering an issue that none of the other similar questions have been able to help me solve. Can anyone offer assistance? I've already attempted removing parameters one by one, but I'm still stuck. Can't resolve all parameters f ...

What is the best way to retrieve a member from a union type?

Here is a simple example to illustrate the problem: // library.d.ts import type { Bar } from './bar.d.ts'; export interface Foo { bar?: string | Bar | boolean; // and many other properties } // bar.d.ts export interface Bar { baz?: number ...

Is it possible to define a constant enum within a TypeScript class?

I am looking for a way to statically set an enum on my TypeScript class and be able to reference it both internally and externally by exporting the class. As I am new to TypeScript, I am unsure of the correct syntax for this. Below is some pseudo-code (whi ...

Angular dynamically filling in a table with incomplete object data

I am currently working on a scientific project that involves displaying large amounts of data in tables. The experiments I'm working with have timestamps that follow this format: interface TimeData { time: string; data: {SD: string, SEM: string ...

Is your Angular5 service failing to transmit data?

I have two components in my code, A and B. Component A contains a form with data that I want to send to component B. However, it seems like component B is not receiving any data. Here is the code for Component A: import { MyService } from 'path/my ...

Can someone assist me in creating mongoose models?

Currently, I am focused on managing products and categories These are the two types I have created: type Category = { parent: Category | null; // Is this acceptable? name: String; }; type Product = { categories: Category[]; name: String; ...

Typescript's date function offers a variety of useful features

Can anyone help me create a function that formats a date string for sorting in a table? The date is in the format: 08.04.2022 16.54 I need to convert this to a number or date format that can be sorted. I'm new to TypeScript and could use some guida ...

Ionic 2 faced an unresolved core-js dependency issue

Recently, I started working on a new Ionic 2 project and encountered an issue when trying to incorporate https://github.com/afrad/angular2-websocket. Upon installation, I received the warning message: UNMET PEER DEPENDENCY core-js@^2.4.1 The template pro ...

There seems to be an issue with Firebase authentication on firebase-admin in node.js. Your client is being denied permission to access the URL "system.gserviceaccount.com" from the server

Issue I've been utilizing Firebase auth on my client and using firebase-admin to verify on the server. It was functioning well until I decided to migrate to a different server, which caused it to stop working. The crucial part of the error message i ...

Issues encountered while retrieving API payload in Reactjs using Typescript

Having some trouble storing an API payload in state, as I keep receiving the following error message: Error: Objects are not valid as a React child (found: object with keys {page, results, total_pages, total_results}). If you meant to render a collection ...

Monitor the change in values upon pressing the submit button on Angular

I am currently working with an edit form that contains data in the input fields. <ng-form #infoForm="ngForm" novalidate> <div> <label for="firstName">First Name :</label> <input type=" ...

Converting a file buffer to upload to Google Cloud Storage

I have been facing an issue while attempting to upload a file to Google Cloud using a buffer and the save function. The problem I am encountering is that even though the files are uploaded to Google Cloud, they are not in the correct format. When I try to ...

Troubleshooting duplicate identifier issue when defining a new class in Typescript

Currently, I am in the process of developing a Linked List using Typescript. I have established an INode interface and a node class as a starting point. interface INode<T> { data: T; next: INode<T> | null; } class Node<T> implements ...