The best approach for sending parameters to the parent class in TypeScript for optimal efficiency

What's the optimal solution to this problem? I really appreciate how we can specify attributes in the constructor and TypeScript takes care of handling everything to assign values to the props in JavaScript - like I did with 'department' here.

However, I'm wondering if there is a convenient way to handle inheritance as well. Is there a method to initialize a subclass with all attributes and pass them to the super call without having to repeat all the properties?

I prefer not to manually list /* all the other attributes of the base class*/ just to initialize the class and fulfill the super call.

Thank you in advance for your assistance.

class Manager extends Employee {
  constructor(public department: number, /* all the other attributes of the base class*/ ){
    super( /* all the other attributes of the base class*/ );
  }
}

let myEmp = new Employee(1, "James"); // Base class
let myMng = new Manager (101, 2, "Jane" ); // Subclass

UPDATE: After receiving valuable feedback on TypeScript techniques, I arrived at this point. I am planning to refine it further to avoid explicitly mentioning and listing superclass members in the super-call. Your thoughts on this approach would be greatly appreciated.

class Manager extends Employee {
  constructor(public department: number, empData: Employee) {
    super(empData.id, empData.name);
  }
}

UPDATE #2 + ANSWER: Thanks to an insightful suggestion from @AluanHaddad and exploring Utility Types in TSC, I found the solution I was searching for.

Big thanks to all of you!

class Employee {
  constructor(public id: number, public name: string) {}
}

class Manager extends Employee {
  constructor(
    public department: number,
    ...superClassData: ConstructorParameters<typeof Employee >
  ) {
    super(...superClassData);
  }
}

let myEmp = new Employee(1, "James"); // Base class
let myMng = new Manager (101, 2,"Jane" ); // Subclass

Answer №1

To simplify the code, consider using the parameter object pattern. Instead of passing multiple parameters, you can pass a single parameter with various fields.

  type EmployeeParams = {
    // include superclass parameters
  }

  type ManagerParams = {
    department: number
  } & EmployeeParams;

  class Employee {
    // define all necessary fields
    constructor(params: EmployeeParams){
      // initialize all fields
    }
  }

  class Manager extends Employee {
    department: number;
    constructor(params: ManagerParams){
      super(params);
      this.department = params.department;
    }
  }

Keep in mind that you must now explicitly specify separate fields within the class.

Answer №2

Instead of passing positional arguments to the constructors, utilize an object with named properties. The "options" object will act as a supertype of the options object for the base class, allowing you to simply pass the entire object:

interface FooArgs {
  a: number
  b: string
}

class Foo {
  public a: number;
  public b: string;

  constructor(args: FooArgs) {
    this.a = args.a;
    this.b = args.b;
  }
}

interface BarArgs extends FooArgs {
  c: number
}

class Bar extends Foo {
  public c: number;
  
  constructor(args: BarArgs) {
    super(args);
    this.c = args.c;
  }
}

Playground

This approach also enhances readability at the call site when creating these objects using new:

const John = new Employee({ age: 32, salary: 60000, name: 'John Smith' });
const Mary = new Manager({ age: 45, salary: 90000, name: 'Mary Brown', directReports: 7 });

Answer №3

Explore how the following code snippets showcase the use of the rest property and type definitions to configure parameters specific to a class.

You can opt to choose between ...

type employeeConfig = {
  field_1: string,
  field_2: number,
}
type managerConfig = {
    department: number,
} & employeeConfig;

class Employee {
  public field_1: string;
  public field_2: number;

  constructor({ field_1, field_2 }:employeeConfig) {

    this.field_1 = field_1;
    this.field_2 = field_2;
  }
}

class Manager extends Employee {
  public department: number;

  constructor({ department, ...restConfig }:managerConfig) {
    super(restConfig);

    this.department = department;
  }
}

const manager = new Manager({ department: 12, field_2: 2, field_1: "foo" });

console.log({ manager });

... or even with ...

type employeeConfig = {
  field_1: string,
  field_2: number,
}
type managerConfig = {
    department: number,
} & employeeConfig;

class Employee {
  constructor(config:employeeConfig) {

    Object.assign(this, config);
  }
}

class Manager extends Employee {
  constructor({ department, ...restConfig }:managerConfig) {
    super(restConfig);

    Object.assign(this, { department });
  }
}

const manager = new Manager({ department: 12, field_2: 2, field_1: "foo" });

console.log({ manager });

The latter approach is more versatile in terms of the parameter configuration but comes at the cost of explicit declaration for any public class fields.

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

Incorporate an HTML span element with an onclick function bound in Angular framework

Is there a way to incorporate different icons by adding a span based on a flag, with an onclick event that triggers an internal function defined in the component ts? testfunc(){ console.log("it works") } flagToIcon(flag: boolean) { switch ( ...

Guide on displaying link parameter information on a separate webpage using only JavaScript

While doing some research, I came across an issue. I have a page called specifications.html with three links: details.html?id=1, details.html?id=2, and details.html?id=3. My goal is to display the details of each link when someone clicks on it. For examp ...

what is the best way to center list items in material ui?

I have been attempting to align the list items (checkbox, text, and buttons) within a Material UI list in the center, but all my attempts have been unsuccessful. Is there anyone who knows how to resolve this issue? Your help would be greatly appreciated! h ...

What is the method to access the information within the observer?

When I receive the data from the observer in the console, here is what I see: https://i.stack.imgur.com/dVzwu.png However, I am only interested in extracting this specific data from each item on the list: https://i.stack.imgur.com/g8oHL.png To extract ...

What is the best way to pass my request data to my $scope variable?

I'm currently facing a challenge with this particular topic. My goal is to add the response data that I retrieve from Express to my angular $scope and then direct the user to their profile page. This is how my Controller Function is structured: $sc ...

Utilize the fitBounds feature from GoogleMaps in Vuejs for seamless integration

I've been working on getting the map boundaries to work properly, using a method in conjunction with my existing initMap and askGeolocation methods. Despite my best efforts, I can't seem to get the bounds functionality working so that the map zo ...

Converting text data into JSON format using JavaScript

When working with my application, I am loading text data from a text file: The contents of this txt file are as follows: console.log(myData): ### Comment 1 ## Comment two dataone=1 datatwo=2 ## Comment N dataThree=3 I am looking to convert this data to ...

Javascript promise failing to deliver

As a beginner in the world of JavaScript development, I am excited to be part of the stackoverflow community and have already gained valuable insights from reading various posts. Currently, I am facing an issue where I need to load a file, but due to its ...

Dynamic text displayed on an image with hover effect using JavaScript

Currently, I am in the process of developing a website for a coding course that is part of my university curriculum. The project specifications require the use of JavaScript, so I have incorporated it to display text over images when they are hovered over ...

Unable to execute internal functional tests due to this error: [POST http://localhost:4444/wd/hub/session] unable to connect - ECONNREFUSED

Currently working with node 0.12 and intern 3 in order to execute functional tests, but encountering the following error: SUITE ERROR Error: [POST http://localhost:4444/wd/hub/session] connect ECONNREFUSED at Server.createSession <node_m ...

Creating Awesome Icons in Kendo Grid with Code In this tutorial, we will learn how to programm

Looking to have a Kendo grid display a green fas-fa-clock icon if isActive is true, and a grey far-fa-clock icon if false. Clicking on the icon should toggle between true and false. Currently, the grid just shows the word true or false in the column. Cod ...

What is preventing me from being able to import a React component from a file?

I've double-checked my code and everything seems correct, but when I view it on the port, only the app.js file is displayed. import React from 'react'; import ImgSlider from './ImgSlider'; import './App.css'; function ...

Ways to store AJAX response data for future use

I am struggling with implementing the getState function. My goal is to update a field on click using a state value retrieved from an AJAX call. I have come across mentions of promises in other responses, but I am unsure how to integrate them into my code ...

Overriding the w-4xl with sm:text-2xl in Tailwind CSS

Struggling to achieve responsive design on my Pages, especially with changing text size when the screen is small. I've been following all the correct steps and maintaining the right order. However, whenever I set 'sm', it seems to override a ...

Mastering the art of duplicating an array of objects in TypeScript

I attempted the following strategy: this.strategies = []; this.strategiesCopy = [...this.strategies]; Unfortunately, it appears this method is not effective as it results in duplicates. ...

Creating a CSS animation to repeat at regular intervals of time

Currently, I am animating an SVG element like this: .r1 { transform-box: fill-box; transform-origin: 50% 50%; animation-name: simpleRotation,xRotation; animation-delay: 0s, 2s; animation-duration: 2s; animation-iterat ...

Update the appearance of a cell if the value within it is equal to zero

I have discovered a way to achieve this using inputs. input[value="0"] { background-color:#F7ECEC; color:#f00;} Now, I am looking for assistance in applying the same concept to table cells. Can anyone provide guidance? Thank you. ...

Error: Unable to access the 'version' property of null

Having trouble installing any software on my computer, I've attempted various solutions suggested here but none have been successful. $ npm install axios npm ERR! Cannot read property '**version**' of null npm ERR! A complete log of this ru ...

Dynamic styling updates on page refresh in Next.js

There is a strange issue with my styling that I can't seem to figure out. I have a NavBar set to be 20vh in height and an image set to be 100% in width. However, whenever I refresh the page, the NavBar height decreases and the image width increases si ...

Tips on incorporating express-mysql-session in a TypeScript project

I'm experimenting with using express-session and express-mysql-session in a Typescript project. Here's the relevant snippet of my code: import * as express from "express"; import * as expressSession from "express-session"; import * as expressMyS ...