Tips on preventing duplicate class properties when they are declared separately from the constructor and then initialized

Imagine you have a simple ES6 class and you want to avoid redundancy by extracting constructor parameters into a separate type. For example:

type BarParams = {
  x: string;
  y: number;
  z: boolean;
};

export class Bar {
  public x: string;
  public y: number;
  public z: boolean;

  constructor({ x, y, z }: BarParams) {
    this.x = x;
    this.y = y;
    this.z = z;
  }
}

Is there a way to prevent duplicating class properties that are identical to the type definition?

Answer №1

Essentially, the goal is to have the constructor implementation appear as follows:

constructor(params: FooParams) { Object.assign(this, params); }

Here, the `Object.assign()` method is utilized to copy all (own, enumerable) properties from `params` into the newly constructed class instance.

However, the challenge lies in informing the compiler that `Foo` should possess the same properties as `FooParams`. One workaround is to employ declaration merging to specify that `Foo` also extends `FooParams`:

interface Foo extends FooParams { }
class Foo {
    constructor(params: FooParams) {
        Object.assign(this, params);
    }
}

This approach ensures the desired functionality:

const foo = new Foo({ a: "hey", b: Math.PI, c: true });
console.log(foo.a.toUpperCase()) // HEY
console.log(foo.b.toFixed(2)) // 3.14

Nevertheless, this solution isn't entirely type safe; declaration merging somewhat resembles a type assertion since the compiler won't "validate" it. If the `Object.assign()` line is omitted from the constructor, the compiler won't detect it, potentially leading to runtime errors. Therefore, caution is advised.

Link to code Playground

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

NestJS does not recognize TypeORM .env configuration in production build

Currently, I am developing a NestJS application that interacts with a postgres database using TypeORM. During the development phase (npm run start:debug), everything functions perfectly. However, when I proceed to build the application with npm run build a ...

Is there a way to retrieve a compilation of custom directives that have been implemented on the Vue 3 component?

Is there a way to retrieve the list of custom directives applied to a component? When using the getCurrentInstance method, the directives property is null for the current component. I was expecting to see 'highlight' listed. How can I access the ...

Asyncronous calls in Angular involve executing tasks without

The issue seems to be related to the timing of updates for the controlSelected and isAssessmentDataLoading variables. The updateQuestions() method is invoked within the ngOnInit() method, which is triggered when the component is initialized. However, the ...

Tips on dynamically looping the formcontrolname and implementing validation strategies

Looking for a way to validate multiple looping of dynamic formControlName="xxx" in select field. Check out my HTML code: <ul *ngFor="let detaillist of stressli.stresstabdetails;"> <li> <div class="form-container"> ...

Renaming personalized elements in Aurelia templates

My inquiry pertains to the process of aliasing custom elements and integrating them into aurelia's html-templates. To set the scene, I am utilizing the latest webpack typescript skeleton available at https://github.com/aurelia/skeleton-navigation and ...

What is the significance of `new?()` in TypeScript?

Here is a snippet of code I'm working with in the TypeScript playground: interface IFoo { new?(): string; } class Foo implements IFoo { new() { return 'sss'; } } I noticed that I have to include "?" in the interface met ...

What is the process of expanding a npm module with TypeScript?

I am currently using joi in conjunction with @types/joi for TypeScript. Joi's extend method allows for the extension of joi by creating a new instance without altering the original joi library. I have successfully created an extended instance using th ...

Unable to access the correct item from local storage while a user is authenticated

I am facing an issue with retrieving the userid from local storage when a user is authenticated or logged in. The user id is not being fetched immediately upon logging in, and even when navigating from one page to another, it remains unavailable until I re ...

The routerLink function with parameters successfully updates the URL, however, it fails to navigate or refresh the component

I have already reviewed a similar question titled router.navigate changes the URL, but is not rendering the component but encountered the same issue in my scenario. Within my routes module, I have a route defined as follows: { path: " ...

The function is not operational while executing addEventListener

I'm encountering some bugs in my Angular 1.5 project with TypeScript. I'm trying to retrieve the scrollTop value from the .uc-card element. public container = document.querySelector(".uc-card"); In my $onInit, I have: public $onInit() { this ...

How can we optimize ternary statements within ternary statements in Type Script and React Native for best practices?

Can you help me optimize this code snippet that uses nested ternary operators for better readability and correctness? <TouchableOpacity style={ darkMode ? filterState === 'A' ? styles.activeButtonDark : styles.buttonDa ...

Could you lend a hand in figuring out the root cause of why this Express server is constantly serving up error

I am encountering a 404 error while running this test. I can't seem to identify the issue on my own and could really use another set of eyes to help me out. The test involves mocking a request to the Microsoft Graph API in order to remove a member fro ...

Utilizing TypedPropertyDescriptor to limit decorators in Typescript when using decorator factories

When it comes to restricting what a decorator can apply on, the standard method involves using a TypedPropertyDescriptor like so: export function decorator(target, key, TypedPropertyDescriptor<T extends ...>) {...} While this approach works well whe ...

Problem encountered when attempting to retrieve information from a web service in Angular 4

I am currently attempting to retrieve data from a web service API. However, all I can see is the data on the console. The web service requires an ID, so I input the ID first and then proceed to obtain the data related to that ID within the web service us ...

Using dual index variables in Angular 4's ngFor loop for iterating through arrays

Is there a way to generate unique index numbers for items printed only on Saturdays? Specifically, I want the index to start from 0 once Saturday begins and continue incrementing. The rest of the options should have the same index numbers. Any suggestions ...

Access SCSS variable values in Angular HTML or TypeScript files

So, I've been looking into whether it's feasible to utilize the SCSS variable value within HTML or TS in Angular. For instance: Let's say I have a variable called $mdBreakpoint: 992px; stored inside the _variable.scss file. In my HTML cod ...

Utilize Typescript to expand the functionality of the Express Request object

Is there a way to add a custom property to the request object in Express middleware using TypeScript without resorting to bracket notation? I am struggling to find a solution that satisfies this requirement. I would ideally like to achieve something like ...

What is the best way to modify an object within a pure function in JavaScript?

Currently, I am exploring different strategies to ensure that a function remains pure while depending on object updates. Would creating a deep copy be the only solution? I understand that questions regarding object copying are quite common here. However, ...

The specified property is not recognized by the type in TypeScript

I have set up a basic form with validation in Ionic 2. The form functioned properly when I used 'ionic serve' but encountered issues when running 'ionic run'. My suspicion is that the problem lies within my TypeScript code, specifically ...

Enhance your TypeScript module with parcel augmentation

I'm having issues shipping a library that utilizes typescript module augmentation with Parceljs. It appears that the module augmentations are not getting bundled properly, preventing me from utilizing the properties in the project that imports the lib ...