Decorator used in identifying the superclass in Typescript

I am working with an abstract class that looks like this

export abstract class Foo {
  public f1() {
  }
}

and I have two classes that extend the base class

export class Boo extends Foo {
}

export class Moo extends Foo {
}

Recently, I created a custom decorator as shown below

export function Bla() {
  return (target: any, key: string, descriptor: PropertyDescriptor) => {
  }
}

Incorporating the decorator into my initial class now looks like this

export abstract class Foo {
 @Bla
 public f1() {
 }
}

I'm trying to figure out if there is a way in the decorator to distinguish where each call originated from, whether it was from Boo or Moo.

So far, I've attempted to check prototypes and constructors of target, but I haven't been able to determine the source class. Is there a method to achieve this or am I approaching it incorrectly?

Any help would be greatly appreciated.

Answer №1

If you want to access the method call itself, one way to do it is by inspecting the class instance:

function CustomFunction(target: any, propKey: string | symbol | d: PropertyDescriptor) {
  let originalMethod = target[propKey];

  // create a new property descriptor for the method, replacing the original one
  return {
    value: function () {
      let instance = this; 
      let classReference = instance.constructor; 

      if (classReference === CustomClass) {
        // perform actions specific to CustomClass
      }

      // call the original method
      return originalMethod.apply(this, arguments);
    }
  }
}

Answer №2

When you apply a decorator to a prototype method, it gets executed when the class containing the decorator is evaluated, not at a later stage when instances are created. The decoration is only applied to the prototype member of that particular class, and subclasses inherit the decorated member.

Consider the following example:

function Bla() {
  return (target: any, key: string, descriptor: PropertyDescriptor) => {
    console.log(target.constructor.name);
  }
}

abstract class Foo {
  @Bla()
  public f1() {
  }
}

// At this point, "Foo" will be displayed in the console

class Boo extends Foo {
}

class Moo extends Foo {
}

The decorator function will execute during the evaluation of class Foo, not when instances are created later on. You can observe this behavior by visiting the playground. If the following code comes after the class definitions mentioned above:

setTimeout(() => {
    new Boo; // No output in the console
    setTimeout(() => {
        new Moo; // No output in the console
        console.log("Done");
    }, 1000);
}, 1000);

If you were decorating an instance member, you could identify the instance as either a Boo or Moo, but distinguishing between them becomes challenging when decorating a prototype member.

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

The React Hook Form's useFieldArray feature is causing conflicts with my custom id assignments

My schema includes an id property, but when I implement useFieldArray, it automatically overrides that id. I'm utilizing shadcn-ui Version of react-hook-form: 7.45.0 const { fields, append, remove, update } = useFieldArray<{ id?: string, test?: n ...

Utilizing Typescript to extract type information from both keys and values of an object

I have a unique challenge of mapping two sets of string values from one constant object to another. The goal is to generate two distinct types: one for keys and one for values. const KeyToVal = { MyKey1: 'myValue1', MyKey2: 'myValue ...

Updating data in Angular reactive forms using asynchronous dropdowns

I am currently developing an Angular application and have encountered an issue that I am unable to resolve by solely reading the documentation. One of the components in my application is responsible for displaying a form: https://i.stack.imgur.com/p5KEU. ...

Here's a revised version: "How to link a lambda layer with a function in a serverless.ts file using the

When working with the serverless framework using the typescript template, a serverless.ts file is generated. I am currently integrating lambda layers with existing functions and encountering a typescript error. The error message reads: "Type '{ Ref: ...

Error: The file named '/accounts.ts' cannot be recognized as a module within a Node.js API

After researching this issue, I have found some answers but none of them seem to solve my problem. Below is the code in my model file: // accounts.ts const mongoose = require('mongoose'); var autoincrement = require('simple-mongoose-autoi ...

A comprehensive guide on displaying data in Angular using an API

I have encountered an issue while trying to display data from an API in the 'home.component.html'. Although my 'home.component.ts' successfully fetches the data from the service, I'm facing difficulty rendering it in 'home.com ...

declaration of function interface and property that cannot be modified

After reviewing some new TypeScript code, I encountered a part that left me puzzled. interface test { (a: number): number; readonly b: number; } While I understand that (a:number): number signifies a function where the argument is a:number and the ret ...

Minimize the amount of information retrieved and shown based on the timestamp

I am currently working on storing and retrieving the date of a user request. For creating the timestamp, I use this code: const date = firebase.firestore.FieldValue.serverTimestamp(); This is how I fetch and display the data: <tr class="tr-content" ...

Trouble with Nested Routing in React Router Version 6: Route not Rendering

I'm facing issues nesting a path within another path in react-router-dom version 6. When I try to visit the nested argument's page (/blog/1), it shows up as a blank non-styled HTML page. However, when I add a child path to the root like /blog, it ...

Enhancing User Authentication: Vue 3 with TypeScript Login

Recently, I came across a new technology called Supabase and noticed that most resources mention registration on JavaScript instead of TypeScript. As I started working on a project using Vue 3 + TypeScript, I encountered some errors that I need help resolv ...

The element at index '0' is not defined for the data type 'number | [number, number]'

In my current project, I have a component named ComponentA which has a defined interface. Here is the snippet of the interface: interface A1 { isSingle: true; value: number; } interface A2 { isSingle: false; value: [number, number]; } exp ...

Resolve an "Uncaught ReferenceError" by importing an unused component to fix the error of not being able to access a variable before initialization

In my service file, where I store all other services used in the frontend, there is an import section that includes one component even though it is not being used. import { VacationComponent } from 'app/view/vacation/vacation.component'; When I ...

I am having trouble getting my custom colors to work with hover effects in Tailwind CSS

The code I have written is for a header component in Next.js with Typescript and Tailwind. I named it Header_2 to represent a component display in a library. Initially, the custom colors were not rendering as expected, but I managed to resolve the issue by ...

Arranging a list of objects with a designated starting value to remain at the forefront

Consider the array and variable shown below: array = ['complete','in_progress','planned']; value = 'planned'; The goal is to always sort the array starting with the 'value' variable, resulting in: array ...

Unable to access 'export default class extends Vue' in the template

I've recently started using Vue.js with TypeScript, but I'm having trouble accessing values from outside the class. @Component({ name: 'SidebarItem', components: { SidebarItemLink } }) export default class extends ...

The object literal is limited to defining recognized properties, and 'clientId' is not present in the 'RatesWhereUniqueInput' type

Currently, I am using typescript alongside prisma and typegraphql in my project. However, I have encountered a type error while working with RatesWhereUniqueInput generated by prisma. This input is classified as a "CompoundUniqueInput" due to the database ...

Is the transcluded content visible to the class as a whole?

Angular2 makes it simple to create a component like this: @Component({ selector: 'some', properties: ['header'] }) @View({ template: ` <div> <h2>{{ getFormattedHeader() }}</h2> <p><conte ...

Using TypeScript with Vue and Pinia to access the store

Is it necessary to type the Store when importing it to TypeScript in a Pinia Vue project? // Component <p>{{ storeForm.firstName }}</p> // receiving an error "Property 'storeForm' does not exist on type" // Store ...

Using renderProps in combination with TypeScript

I've encountered an issue while trying to convert my React project to TypeScript, specifically with the login component that uses react-google-login. The error I'm facing is related to renderProps: Overload 1 of 2, '(props: { component: El ...

turning off next.js server side rendering in order to avoid potential window is undefined issues

I am currently managing a private NPM package that is utilized in my Next.js project, both of which are React and Typescript based. Recently, I integrated a graph feature into the NPM package and encountered an issue where any reference to window within t ...