The comparison between using Reflect.decorate and manual decorating in TypeScript

Here are two different decorators that I am using:

import "reflect-metadata";

const enum MetadataTypes {
  Type = "design:type",
  Paramtypes = "design:paramtypes",
  ReturnType = "design:returntype"
}

function DecoratorA(target: any, key: string): void {
  console.log(`Applied DecoratorA to ${key} on ${target.constructor.name}`);
  const type = Reflect.getMetadata(MetadataTypes.Type, target, key);
  console.log(type.name);
}

function DecoratorB(target: any, key: string): void {
  console.log(`Applied DecoratorB to ${key} on ${target.name}`);
  const type = Reflect.getMetadata(MetadataTypes.Type, target, key);
  console.log(type);
}

I have applied one manually like this:

export class MyClass {
  @DecoratorA
  private foo: string;
}

And the other is applied using Reflect.decorate:

Reflect.decorate([DecoratorB], MyClass, "foo");

I noticed that the decorator applied with Reflect does not retrieve the data type correctly. Why do you think this could be happening?

The output logs are as follows:

Applied DecoratorA to foo on MyClass
String

Applied DecoratorB to foo on MyClass
undefined

Answer №1

If you want to achieve a similar behavior using Reflect.decorate, you need to provide the class prototype.

import "reflect-metadata";

const enum MetadataTypes {
  Type = "design:type",
  Paramtypes = "design:paramtypes",
  ReturnType = "design:returntype"
}

function CustomDecorator(target: any, key: string): void {
  console.log(`Applied CustomDecorator to ${key} on ${target.constructor.name}`);
  const type = Reflect.getMetadata(MetadataTypes.Type, target, key);
  console.log(type.name);
}

export class MyClass {
  private foo: string;
}

Reflect.decorate([CustomDecorator], MyClass.prototype, "foo");

// Output:
// Applied CustomDecorator to foo on MyClass
// undefined

The issue here is that metadata isn't created when using Reflect.decorate.

By utilizing a decorator syntax, the compiler will store metadata (when the emitDecoratorMetadata configuration option is enabled), which can then be accessed through Reflect.getMetadata.

You can find more information about this topic here: https://github.com/Microsoft/TypeScript/issues/2577

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 Service Injection and Factory Pattern in Angular 8

After going through various articles and official Angular guides, it appears that they were unable to assist me in solving my task. Here's what I wanted to achieve: Imagine having an Angular application with a product listing page. Additionally, this ...

Despite passing the same dependency to other services, the dependencies in the constructor of an Angular2 Service are still undefined

To successfully integrate the "org-agents-service" into the "org-agents-component," I need to resolve some dependencies related to the required api-service. Other components and services in the hierarchy are also utilizing this api-service, which acts as a ...

Can one invoke ConfirmationService from a different Service?

How can I declare an application-wide PrimeNG dialog and display it by calling ConfirmationService.confirm() from another service? Below is the HTML code in app.component.html: <p-confirmDialog [key]="mainDialog" class="styleDialog" ...

Disabling aria-label enforcement for icon-buttons in Chakra UI Typescript

Having a Chakra UI icon button, I am facing an issue with the aria-label attribute. The IconButton is within an aria-hidden section in the tree; therefore, the label becomes redundant. If I try to remove the aria-label, TypeScript throws complaints as sho ...

The CSS files are not loading automatically in my React application using Vite

I am facing an issue with importing css and js files into a view in React using vite. The styles are not loading properly, and I have to keep commenting and uncommenting the imports in my code for them to be recognized when entering the view. Below is a s ...

How to dynamically add an HTML element following a specific div class in Typescript and Angular

Is there a way to dynamically insert a component into a div after a specific element with a designated class name using TypeScript? <div class ="{{order.orderId}}"> <div class="enter-here"></div> <other html elements here> < ...

UI-Router - issue with query parameters preventing arrays with only one item

My application utilizes UI-Router, specifically with a state named Widgets that includes a query parameter accepting an array of widgets: const widgetsState = { name: "widgets", url: "/widgets?{widgets:string[]}", component: Widgets, pa ...

Latest Angular 2 Release: Lack of visual updates following asynchronous data entry

Currently, I am working with Angular2-Beta1, However, the templating from the "*ngFor" is not working properly and is only displayed as <!--template bindings={}--> and not as <template ...></template> as described here on the Angular2 G ...

Is there a more efficient method for providing hooks to children in React when using TypeScript?

My component structure looks something like this: Modal ModalTitle ModalBody FormElements MySelect MyTextField MyCheckbox DisplayInfo ModalActions I have a state variable called formVars, and a function named handleAction, ...

Tips for successfully transferring a JsonifyObject<T> from Remix's useLoaderData<typeof loader> to a function

Encountering a TypeScript error while trying to import JsonifyObject in the Remix 2.9.2 route code below... Argument of type 'JsonifyObject<IdAndDate>' is not assignable to parameter of type 'IdAndDate'. Struggling to figure ou ...

Is there a way to make a peer dependency optional in a project?

In the process of developing module A, I have implemented a feature where users can choose to inject a Winston logger into my module. As a result, winston becomes a peer dependency. However, when attempting to include module A in another module without th ...

changing an array into json format using TypeScript

Looking to convert an array into JSON using TypeScript. How can I achieve the desired result shown below? let array = ['element1', 'element2', 'element3'] result = [{"value": "element1"}, {"value": "element2"}, {"value": "el ...

Incorporate a personalized Material UI checkbox within a column of the Material React table

Starting out with React, I decided to incorporate Material React Table v2 into my project. My goal is to include a Material UI checkbox that accurately represents the 'Is Active' data in a disabled state. Despite numerous attempts, I have not bee ...

Is there a more effective way to implement a Custom Validator using .forEach?

I have developed my own validation class as a learning exercise. Do you think this is an effective approach, or do you have suggestions for improvement? import { AbstractControl } from '@angular/forms'; export class ProjectNameValidator { pr ...

Replace Formik with useFormik to streamline your code

I have implemented Formik/Yup for validation on a page that triggers a GraphQL mutation. The code is functioning as expected: export default function RemoveUserPage() { const [isSubmitted, setIsSubmitted] = useState(false); const [isRemoved ,setIsRemo ...

How can I transfer data to a different component in Angular 11 that is not directly related?

Within the home component, there is a line that reads ...<app-root [message]="hii"> which opens the app-root component. The app-root component has an @input and {{message}} in the HTML is functioning properly. However, instead of opening t ...

An error in typescript involving a "const" assertion and a string array

Currently, I am diving into the world of Typescript along with React. However, an error has emerged in my path that I can't seem to figure out. It's puzzling why this issue is occurring in the first place. Allow me to elaborate below. const color ...

Map does not provide zero padding for strings, whereas forEach does

Currently working on developing crypto tools, I encountered an issue while attempting to utilize the map function to reduce characters into a string. Strangely enough, one function works perfectly fine, while the other fails to 0 pad the string. What could ...

In Angular, I aim to invoke the this.addDispatchToReceive method whenever the outcome is successful within each forEach iteration

How can I ensure that the values from this.stockItemDispatch are obtained in this.addDispatchToReceive(); during each iteration of a loop, instead of only getting the last stock value? The issue is that the subscribe function runs after the foreach cycle ...

The issue at hand is that the Mongo Atlas model is in place, but for some reason,

I recently delved into using Next.js and I am a newcomer to backend technologies. I have successfully established a connection with MongoDB Atlas using Mongoose, however, the user object data from the post request is not being created as a document in th ...