Can class properties be automatically generated based on its generic type?

Is it possible in TypeScript to automatically create a class with properties based on its generic type? For example:

class CustomClass<T> {
  // Code to extract properties from T should go here
}

interface Characteristics {
  quality: string;
  price: number;
}

const item = new CustomClass<Characteristics>;

// Now, both item.quality and item.price will be available for autocompletion with the correct types specified in the 'Characteristics' interface

interface Attributes {
  color: string;
  size: number;
  weight: number;
}

const product = new CustomClass<Attributes>;
// Only the three attributes defined in 'Attributes' interface will be accessible for 'product'

I am looking for a solution that does not involve adding something like

class SomeClass {
  [property: string]: any
}

as this would allow any property to be added, whereas I specifically want to limit the properties to those defined in the generic type.

Answer №1

For the specific scenario you're describing, a mixin approach is more appropriate than traditional inheritance. However, TypeScript does not support generic mixins of the sort interface X<T> extends T.

To work around this limitation, you can define an object called SomeClass and a generic type named SomeClass<T>. You would need to incorporate some type assertions to make it functional. Below is a possible implementation:

class _SomeClass<T> {
    constructor(t: T) {
        Object.assign(this, t);
    }
    
    get<K extends keyof T>(k: K): T[K] {
        return (this as any as T)[k]; // assertion
    }
}
type SomeClass<T> = T & _SomeClass<T>;
const SomeClass = _SomeClass as new <T>(t: T) => SomeClass<T>;

Hopefully, this provides some insight into working with TypeScript in scenarios where certain features are not directly supported. Good luck!

Answer №2

Classes are unable to utilize mapped types. However, with inspiration from the response found at: , a workaround can be achieved by creating a function that generates an object conforming to a specified interface:


interface Data {
  x: string;
  y: number;
}

function generate<T>(data?: T): T {
  return Object.assign({}, data);
}


const newData = generate<Data>();
// The newData object now includes properties x and y

// Alternatively, default values can be passed in
// const anotherData = generate<Data>({ x: 'example', y: 42 });    

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

I am puzzled as to why I am still facing the error message: "'node' is not recognized as an internal or external command, operable program or batch file."

I'm in the process of setting up typescript for a new node project. Here are the steps I've taken so far: Installing typescript: npm i --save-dev typescript Installing ts-node: npm i --save-dev ts-node Installing the types definition for node ...

Rejecting the request by clicking a button

While switching to a menu, I retrieve data from the API. As the pending data is still loading in DevTools, I click on the Filter button to search for additional data. The data I am searching for appears in my table. However, once the pending data finishes ...

I have successfully set up micro-cors on my system, and as I tried to compile, I received the following outcome

While working on the Next.js Stripe project, I ran into an unexpected problem that I need help with. ./src/pages/api/webhooks.ts:3:18 Type error: Could not find a declaration file for module 'micro-cors'. 'E:/Project/longlifecoin/node_module ...

Is it possible for TypeScript to deduce the type of a discriminated union using "extracted" boolean logic?

Recently, I've been using discriminated unions (DU) more frequently and have really started to appreciate their benefits. However, I've encountered a challenge that I can't seem to resolve. When I include a boolean check inline for the DU, T ...

Executing a child component function once the parent component data is loaded in Angular 5

In my project, I have a parent component called program-page.component where I am invoking a function to fetch some data. ngOnInit() { this.getProgress(); } getFirstProgramItem() { this._contentfulService.getProgramItem(4, 1) .then((programItem) = ...

Alert: Using Angularfire SDK could result in console log issues

I've been encountering this persistent warning that I just can't seem to get rid of no matter what I try. Here are the versions I'm using: angular 11.0.1 @angular/fire 6.1.3 firebase 7.0.0 || 8.0.0 https://i.sstatic.net/5Tyt5.png ...

Is it possible to define data types for the global context in cucumber?

Embarking on a fresh cucumber-selenium project in Typescript, I am eager to keep the Driver in the world context. However, following the method suggested here, I encounter an issue where the Driver type remains inaccessible to step definitions. This means ...

What is the best way to obtain the dimensions of an image in Angular 2 (or newer) before uploading it to the server, and can this be accomplished without utilizing jQuery?

After searching through multiple resources, I realized that most of the solutions are written in jQuery. However, I am specifically looking for a solution in Typescript. The HTML code snippet is as follows: <input #coverFilesInput class="file-input" t ...

Using React.useMemo does not efficiently avoid unnecessary re-renders

In my code, I am working with a simple component as shown below: const Dashboard = () => { const [{ data, loading, hasError, errors }] = useApiCall(true) if (hasError) { return null } return ( <Fragment> <ActivityFeedTi ...

Best practice in Angular 2: The difference between binding an object as a whole versus binding its individual

What is the best approach for a child component when dealing with object properties and change events? Example 1 <parent-component> <child-component [exampleInput]="object.val" (valueChanged)="updateObjectValue($event)"> ...

Guide on creating a Typescript Conditional type structure for Array elements that rely on each other

In my function, I am working with an array of objects that contain an icon key. If one index in the array has a value assigned to the icon key, then another index should also have a value. If one index leaves the icon key undefined, then another index shou ...

Guide to accessing nested form controls within an array and object in Angular Reactive Forms

As a newcomer to Angular, I am in the process of creating a complex form for a food delivery application that I have been developing. The form I am currently working on is designed to allow me to add a new menu item to a restaurant's menu. In this A ...

Experience screen sharing through WEBRTC without the need for any additional browser extensions

One question that I have is: Is it possible to implement screen sharing that works on a wide range of devices and browsers without the need for plugins or experimental settings? I have searched online and come across some plugins for Chrome, but I am look ...

Learn how to open a component in a new browser tab using Angular from a different component

I wish to display the MapComponent in a new browser tab when a button in my AppComponent html file is clicked. Currently, when I click the button, the MapComponent opens in a new tab but it also displays the button. How can I configure it so that only the ...

A guide on retrieving data from Promises in Angular

After executing a promise, I am looking to access the data that is returned as a JSON hashmap. Each key and its corresponding value needs to be displayed in separate dialog boxes: I have attempted to access the data using the following method: component. ...

Is the event emitter contained within the subscription?

I have an issue where I need to update my chart component after inputting values into a form field. However, I am unsure of how to accomplish this task. This is the code in my start.component.html file: <input [(ngModel)]="inputValue"/> <select ...

Sorting the table in Angular Material is proving to be a challenge

I'm attempting to organize data within an Angular table by utilizing the MatSortModule. Unfortunately, the sorted table is not functioning correctly. Below is the provided code: main.module.ts import { MatTableModule, MatSortModule } from '@ang ...

Trouble integrating PDF from REST API with Angular 2 application

What specific modifications are necessary in order for an Angular 2 / 4 application to successfully load a PDF file from a RESTful http call into the web browser? It's important to note that the app being referred to extends http to include a JWT in ...

Gradle synchronization in IntelliJ causing missing folders in WAR Artifact

Currently, I am working on a Spring MVC application that incorporates TypeScript. The TypeScript code is transpiled using a Gradle task from the directory src/main/ts to build/ts. Subsequently, the resulting JavaScript files are added to the WAR file usin ...

Tips for retrieving an item from a (dropdown) menu in Angular

I am facing an issue with selecting objects from a dropdown list. The array called "devices" stores a list of Bluetooth devices. Here is the HTML code: <select (change)="selectDevice($event.target.data)"> <option>Select ...