Utilizing Generics in TypeScript to Expand Abstract Classes

How can I define the property eventList in the class ImplTestClass to be an array with all possible values of AllowedEvents, while extending the class TextClass that accepts T?

I'm stuck on this one. If anyone can provide guidance on how to achieve this, I would greatly appreciate it!

type EventMap = Record<string, unknown>; 

abstract class TestClass<T extends EventMap> {
  public eventList: Array<T[keyof T]>;

  constructor() {
    this.eventList = [];
  }
}


interface AllowedEvents extends EventMap {
  created: { time: string; userId: number; createdId: number; },
  removed: { time: string; userId: number; removedId: number; }
}

class ImplTestClass extends TestClass<AllowedEvents> {
  getEventList() {
    return this.eventList;
    // I would like `eventList` to have the type 
    // ({ time: string; userId: number; createdId: number; } | { time: string; userId: number; removedId: number; })[]
  }
};


Answer №1

One way to achieve this is by utilizing a type alias instead of an interface¹ and omitting the explicit extension of EventMap:

type AllowedEvents = {
    created: { time: string; userId: number; createdId: number };
    removed: { time: string; userId: number; removedId: number };
};

The AllowedEvents type is a suitable subtype of Record<string, unknown>, enabling it to be used as the type argument for the abstract base class. This allows the subclass code to access the desired type for eventList.

Playground link


¹ For what it's worth: I'm uncertain why it must be a type alias rather than an interface. I attempted to use it as an interface and TypeScript refused to allow it as the type argument for the base class, citing a lack of an index signature.

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

Exploring the process of retrieving data from localStorage in Next.js 13

Having recently delved into the realm of Next JS, I've encountered a hurdle when it comes to creating middleware within Next. My aim is to retrieve data from local storage, but I keep hitting roadblocks. middleware.ts import { key, timeEncryptKey, to ...

Unveiling the Ultimate Method to Package Angular 2 Application using SystemJS and SystemJS-Builder

I'm currently in the process of developing an application and I am faced with a challenge of optimizing the performance of Angular 2 by improving the loading speed of all the scripts. However, I have encountered an error that is hindering my progress: ...

error TS2339: The attribute 'properties' is not accessible on the class 'TestPage'

Utilizing a typescript abstract class as the base class of my layout component in React has been essential for my project. The implementation of this base class looks something like this: import { IPageLayoutActions, IPageLayoutLocalState, IPageLayoutProp ...

Node.js and mongoose provide a powerful tool for filtering documents dynamically by leveraging a variable that is dependent on another document. Want to learn

I've hit a bit of a roadblock here... I'm trying to add a new property to a document that will change based on the values in that document as well as another document. Let me provide an example to clarify. First, I have a Candidate Schema: const ...

Error caused by properties of a variable derived from an interface in the compiler

I'm confused as to why the compiler is saying that the properties "name" and "surname" don't exist on type "ITest1" within function test1. It's a bit unclear to me: interface ITest1{ name: string; surname: string; age: number; } ...

What is the best way to display HTML file references in TypeScript files using VSCode when working with Angular templates?

Did you know that you have the option to enable specific settings in VSCode in order to view references within the editor? Take a look at the codes below: "typescript.implementationsCodeLens.enabled": true, "javascript.referencesCodeLens.enabled": true I ...

Decrease initial loading time for Ionic 3

I have encountered an issue with my Ionic 3 Android application where the startup time is longer than desired, around 4-5 seconds. While this may not be excessive, some users have raised concerns about it. I am confident that there are ways to improve the ...

Explore the use of enumerations within a class

My code structure includes: position.utils.ts enum PositionDirectionEnum { LEFT, RIGHT, TOP, BOTTOM, AUTO } export class PositionUtil { public static PositionDirection: PositionDirectionEnum } utils.ts import { PositionUtil } from "./position. ...

Comparison between typings and @types in the NPM scope

There are different approaches when it comes to handling TypeScript definitions. In some cases, the typings tool is used, as seen in projects like angular/angular2-seed. Alternatively, some projects use scoped NPM packages with the prefix @types, complete ...

Setting up an empty array as a field in Prisma initially will not function as intended

In my current project using React Typescript Next and prisma, I encountered an issue while trying to create a user with an initially empty array for the playlists field. Even though there were no errors shown, upon refreshing the database (mongodb), the pl ...

Even when I try to access the properties of the arguments object, it remains empty and has a zero

Why is the arguments object showing a length of zero when I pass parameters to the function, even though I can still access its properties? I am referring to the arguments object that is implemented by all JavaScript functions, allowing you to access the f ...

Encountering a Typescript issue while trying to access two distinct values dynamically from within a single object

Currently, I'm developing a component library and facing an issue with a TypeScript error: An Element implicitly has an 'any' type due to the expression of type 'levelTypes | semanticTypes' being unable to index type '{ level1 ...

What is the correct way to handle the return value of an useAsyncData function in Nuxt 3?

How can I display the retrieved 'data' from a useAsyncData function that fetches information from a pinia store? <script setup lang="ts"> import { useSale } from "~/stores/sale"; const saleStore = useSale(); const { da ...

Error in TypeScript: Angular Jasmine - The argument given as type 'string' cannot be assigned to a parameter expecting type 'never'

Currently, I am in the process of writing test cases for Angular using Jasmine 3.6.0 and TypeScript 4.1.5 with "strict": false set in my tsconfig.json file. One particular task involves spying on a component method called 'close', and following ...

Having trouble retrieving the JSON data from the getNutrition() service method using a post request to the Nutritionix API. Just started exploring APIs and using Angular

When attempting to contact the service, this.food is recognized as a string import { Component, OnInit } from '@angular/core'; import { ClientService } from '../../services/client.service'; import { Client } from '../../models/Cli ...

Styling with react-jss based on intricate conditionals

After experimenting with react-jss for a few weeks, I am faced with the challenge of styling components efficiently. With numerous conditionals in these components, I am striving to avoid creating an excess of new components that essentially share the same ...

Creating a second optional generic parameter in TypeScript

I'm having trouble with TypeScript generics My issue is as follows: I have an interface called 'Column' and a function called makeColumn to create a new column. I want to only set the first generic (UserModel), where the accessor must be a ...

Stop users from switching to other tabs within mat-tab-group without using ViewChild

I am working with a mat-tab-group component in Angular : mat-tab-group class="brand-tabs" [disableRipple]="true" *ngSwitchCase="types.project" (selectedTabChange)="changeProjectTab($event)" [selectedIndex]="selectedProjectIndex" > . ...

Navigating UnwrapRefSimple in Vue Composition API and TypeScript: Best Practices

When I utilize reactive objects in Vue Composition API, I encounter Typescript errors relating to UnwrapRefSimple<T>. This issue appears to be specifically tied to using arrays within ref(). For instance: interface Group<T> { name: string ...

What is the best way to incorporate my own custom component into the Mui Theme options in order to efficiently modify it?

I've been grappling with this issue for a while now and I just can't seem to get past these type errors. It feels like there's a crucial piece of the puzzle that I'm missing. My goal is to develop my own custom component and then have ...