What methods does Angular use to determine the parameter types of a constructor?

I've been experimenting with replicating Angular's approach to interpreting the constructor in an injectable service.

function Injectable() {
  return function<T extends { new (...args: any[]): {} }>(con: T) {
    return class extends con {
      static __constructorClasses: any[] = [];

      constructor(...args: any[]) {
        super(...args);
        Foo.__constructorClasses = ???;
      }
    };
  };
}

How can I populate Foo.__constructorClasses with a list of classes?

class Bar {
  public hello = 'world';
}

@Injectable()
class Foo {
  constructor(private bar: Bar) {}
}

// I expect: Foo.__constructorClasses = [Bar]
const bar = new Foo.__constructorClasses[0]();
console.log(bar.hello) // 'world'

Is my approach incorrect? My objective is to identify each class in the constructor, either as the class itself [Bar] or as a string representing the class 'Bar'. Using a string is also acceptable as it can be utilized to retrieve the Bar instance from a Proxy.

Answer №1

Using:

  • typescript: 3.5.3
  • reflect-metadata: 0.1.13

Command for execution:

tsc foo.ts --emitDecoratorMetadata --experimentalDecorators && node foo.js

foo.ts code snippet:

import 'reflect-metadata';

type Constructor<T> = { new (...args: any[]): T };

function Injectable() {
  return function _Injectable<T extends Constructor<{}>>(Base: T) {
    return class __Injectable extends Base {
      classes: any[] = Reflect.getMetadata(
        'design:paramtypes',
        __Injectable.prototype.constructor
      );

      constructor(...args: any[]) {
        super(...args);
      }
    }
  };
}

class Bar {
  label: string;

  constructor() {
    this.label = 'BarClass';
  }
}

@Injectable()
class Foo {
  constructor(private bar: Bar) {}
}

const bar = new Bar();
const foo = new Foo(bar);

//@ts-ignore // ts doesn't strictly know that classes exists on Foo
console.log(foo.classes); // [ [Function: Bar] ]
//@ts-ignore // ts doesn't strictly know that classes exists on Foo
console.log(new foo.classes[0]().label); // 'BarClass'

The main information was provided here: https://www.typescriptlang.org/docs/handbook/decorators.html but I wanted to show a simple example of how Typescript emits the classes passed to a class constructor.

For more details:

https://codeburst.io/decorate-your-code-with-typescript-decorators-5be4a4ffecb4

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

Angular Floating Panels: A Guide to Creating Dynamic User Interfaces

In the process of developing an angular app, I require a dock-able panel. After researching available controls online, I found them difficult to use and they compromised our screen layout. As a result, I am considering building a custom dock panel from s ...

Storing the typeof result in a variable no longer aids TypeScript in type inference

Looking at the code snippet below: export const func = (foo?: number) => { const isNumber = typeof foo === 'number'; return isNumber ? Math.max(foo, 0) : 0; }; A problem arises when TypeScript complains that you cannot apply undefined to ...

What is included in the final Angular build package selection?

Is there a tool available to track packages included in the final build of an Angular project? For instance: I am using the package "@angular/compiler" as a dependency in my package.json, but it is not a dev dependency. According to the Angular ...

Having trouble binding component property in VueJS with TypeScript?

Why is my component property not binding when I set the related component attribute to a value? Even when inspecting with Vue devtools or outputting the value into the HTML, it remains at the default value set on the component. I tried setting a string at ...

Modify the CSS for the selected values in an angular material multi-select component

I am looking to customize the CSS for selected values in a material multi select. <mat-form-field class="mat-form-field-fluid"> <mat-select placeholder="User Permissions" [(value)]="selectedPermissions" multipl ...

Implement a click event for the X-Axis label in Angular 2 Highcharts

I'm currently facing a challenge with hand-rolling a solution that involves adding a click listener to an X-Axis label in a column chart using the HighCharts API within an Angular 2+ application. Here is what I have gathered so far: I am utilizing ...

Struggling to utilize a custom react-three-fiber component despite specifying the custom type within the react-three-fiber module

Currently developing a react application focused on visualizing mathematical concepts with the help of react-three-fiber. Utilizing TypeScript, I discovered that by extending custom ThreeElements (https://docs.pmnd.rs/react-three-fiber/tutorials/typescript ...

Error message: Deno package code encounters error due to the absence of 'window' definition

I am facing an issue with a npm package I imported into my Deno project. The code in the package contains a condition: if (typeof window === 'undefined') { throw new Error('Error initializing the sdk: window is undefined'); } Wheneve ...

A deep dive into TypeScript: enhancing a type by adding mandatory and optional fields

In this scenario, we encounter a simple case that functions well individually but encounters issues when integrated into a larger structure. The rule is that if scrollToItem is specified, then getRowId becomes mandatory. Otherwise, getRowId remains option ...

Creating a dynamic return statement in typescript: A step-by-step guide

I am looking to dynamically set a return value to a variable based on values retrieved from an API. The current function in question uses static values: this.markDisabled = (date: NgbDate) => { return (this.calendar.getWeekday(date) !== 5 && ...

Implementing conditional asynchronous function call with identical arguments in a Typescript React project

Is there a way in React to make multiple asynchronous calls with the same parameters based on different conditions? Here's an example of what I'm trying to do: const getNewContent = (payload: any) => { (currentOption === myMediaEnum.T ...

Switching the focus of detection from a child to a parent

I am currently working on enhancing the functionality of my UI to display selections dynamically as they are selected or de-selected. import { Wizard } from './report-common'; import { Router } from '@angular/router'; import { DataServ ...

What is the best way to specify the return type in TypeScript when there is a possibility of multiple types?

I'm currently working on implementing type definitions for an Axios API client but I’m struggling with indicating to the compiler the specific return type that I am expecting. Here is a simplified example: import axios, { AxiosResponse } from "axi ...

Oops! The type '{}' is lacking the properties listed below

interface Human { firstName: string; lastName: string; } let human1: Human = {}; human1.firstName = "John" human1.lastName = "Doe" Upon declaring human1, an error pops up: Type '{}' is missing the following properties from type Human ...

Angular2 - Breaking down applications into reusable components

Utilizing custom properties permits seamless data binding between multiple components. <section id="main"> <app-home [dict]="dict">Hello there!</app-home> </section> In this scenario, dict serves ...

Using Typescript: ForOf Iteration with Unknown Value Types

My journey began with a quick peek at this particular inquiry. However, the approach discussed there utilized custom typing. I am currently iterating over object entries using a for-of loop. Here's a snippet of the values I'm dealing with below. ...

Tips for parsing text responses in React to generate hyperlinks and emphasize specific words

I'm currently tackling a React project and facing an interesting challenge. I have a text response that needs to be parsed in a way that all URLs are automatically turned into clickable hyperlinks (using anchor tags). Moreover, there's a requirem ...

Peer dependencies in NPM refer to dependencies that your project

I am currently in the process of upgrading from Angular 4 to Angular 5 and encountered some warnings along the way. Some of the warnings I received include: npm WARN @angular/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="88eb ...

Changing the background color of a selection in Angular can be customized by modifying

Is there a way to customize the background color of a select element in Angular? I would like to change the default grey background to white. How can this be achieved? Below is the code for my select element: <select id="areaOfExpertiseFilter" ...

What is the process of creating a for loop in FindById and then sending a response with Mongoose?

Is there a way to get all the data in one go after the for loop is completed and store it in the database? The code currently receives user object id values through req.body. If the server receives 3 id values, it should respond with 3 sets of data to th ...