The second property decorator is experiencing issues with the Setter/Getter functionality not functioning properly

Having encountered an issue with my two decorators, I noticed that only the first decorator defined is executing its setter/getter properties when attached to a property. The inner function itself triggers both `Init Decorator 1` and `Init Decorator 2`. What could be causing the second decorator to not execute its setter/getter?

Below are how the two decorators are defined:

export function Decorator1(): any {
  return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
    descriptor = descriptor || {};
    console.log('Init Decorator 1');
    descriptor.get = function (this: any) { console.log('Get Decorator 1'); }
    descriptor.set = function (this: any) { console.log('Set Decorator 1'); }
    return descriptor;
  }
}
export function Decorator2(): any {
  return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
    descriptor = descriptor || {};
    console.log('Init Decorator 2');
    descriptor.get = function (this: any) { console.log('Get Decorator 2'); }
    descriptor.set = function (this: any) { console.log('Set Decorator 2'); }
    return descriptor;
  }
}

The decorators are used as shown below:

export class Test {
  @Decorator1()
  @Decorator2()
  code = '';

  constructor() {
    setTimeout(() => this.code = '123', 2000);
  }
}

new Test();

Playground Example

[LOG]: "Init Decorator 2" 
[LOG]: "Init Decorator 1" 
[LOG]: "Set Decorator 1" 
[LOG]: "Set Decorator 1" 

Answer №1

As per the documentation on accessor decorators in TypeScript, a decorator that returns a value will replace the existing property descriptor for the specified property. Additionally, when multiple decorators are applied, they execute from bottom to top.

For instance, in the provided code snippet:

@Decorator1()
@Decorator2()
code = '';

The initial property descriptor is replaced with the descriptor defined by Decorator2. Subsequently, this descriptor is modified by updating its get and set properties. Reassigning these properties does not retain any previous values, leading to the loss of the set() method content set by "Set Decorator 2."


The approach to composing property descriptors is left to the developer's discretion. It is advisable to examine the passed descriptor value in the decorator function and preserve its get and set properties as needed. One potential strategy is illustrated below:

return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
  descriptor = descriptor || {};
  const prevGet = descriptor.get;
  const prevSet = descriptor.set;
  console.log('Init Decorator N');
  descriptor.get = function (this: any) {
    console.log('Get Decorator N');
    if (prevGet) prevGet.call(this);
  }
  descriptor.set = function (this: any, v) {
    console.log('Set Decorator N');
    if (prevSet) prevSet.call(this, v);
  }
  return descriptor;
}

In this implementation, the prior get and set values are stored and called within the new methods, respecting their order based on necessity. Remember that handling the return values of previous methods, especially for get, may be crucial. The key takeaway is the explicit consideration of the existing descriptor state for preservation purposes.

Utilizing such an approach yields the following outcomes:

[LOG]: "Init Decorator 2" // Decorator2 is executed first
[LOG]: "Init Decorator 1" // Followed by Decorator1 
[LOG]: "Set Decorator 1" // Execution of Decorator1 logic precedes
[LOG]: "Set Decorator 2" // Decorator2's logic is invoked within the set action of Decorator1
[LOG]: "Set Decorator 1" // Likewise
[LOG]: "Set Decorator 2" // Likewise

Access the code on 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

Generate unique identifiers to rotate images dynamically on the webpage

My goal is to rotate every image on a page, and while this works with a single image, it only rotates the first one since each ID needs to be unique. I need to find a way to dynamically increment the IDs as they are encountered on the page. Below is what I ...

What is the process for creating a symbolic link from a project's node_modules directory?

Recently, I've been learning how to build a Password Manager using React, Node.js, and MYSQL by following a tutorial. However, I encountered an issue where the file /EncryptionHandler was located outside of the src/ directory of my project. Even thoug ...

Exploring the capabilities of Vue.js, including the use of Vue.set()

Just starting out with Vuejs and I have a query regarding the correct approach to achieve what I want. My Objective I aim to have some dates stored in an array and be able to update them upon an event trigger. Initially, I attempted using Vue.set, which ...

Exploring and verifying data within an array in ReactJS

In ReactJS, there is a variable that contains the result of validation as an array: console.log(this.state.check); // [account: false, name: true, email: true] Here's what needs to be done: If all values in the array are true, return true. If one or ...

Can you explain the significance of 'Symbol(isOptimistic): false | true' in a mutation request sent through AppSync, Graphql, and Apollo?

Recently, I delved into the realm of GraphQL with AppSync. Initially, my API was functioning smoothly and efficiently, utilizing a combination of: React Apollo TypeScript However, after incorporating additional features, the API ceased to store new data ...

What is the best way to create a sidebar that remains open without triggering a new sidebar every time it is clicked

I am looking to add a sidebar that opens a new view without navigating to a different page. The sidebar remains consistent and I want to avoid duplicating it on all pages. Check out this photo for an example. My goal is to provide additional content or fe ...

What steps should I take to develop an Outlook add-in that displays read receipts for action items in sent emails?

Currently, I am in the process of developing an add-in that will enable me to track email activity using a tool called lead-boxer (). With this add-in, I am able to retrieve detailed information about users who have opened my emails by sending them with an ...

Arrange the data in the table to ensure that it is organized neatly into the appropriate columns

I am currently working on a project that involves creating a table to display user answers for purchased tickets under the corresponding questions. If a question has not been answered, I want to show a dash symbol instead. However, I am encountering an is ...

Concealing a DIV element when the value is not applicable

I'm currently working on a website for a coffee shop product. On this site, each product has a coffee strength indicator that is determined by the database. The strength can be categorized as Strong, Medium, Weak, or n/a (for non-coffee products). If ...

Store user input in a paragraph

I want to create a unique program that allows users to input text in a field, and when they click "Start", the text will appear in a paragraph backwards. I plan to use Html, jQuery, and CSS for this project. Can anyone provide guidance on how to achieve th ...

Develop a React component that organizes an array based on specified index ranges in JavaScript

Imagine having an array structured like this: let numbers = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17, 18, 19]; I am interested in creating a React component that displays the elements of the array in groups of 10. The desired output should look like t ...

Exploring the world of ASP .NET development with the powerful Sonar

We're currently working on an ASP .NET project and are looking for a way to analyze JavaScript files on-the-fly. Unfortunately, SonarLint only offers analysis for C# files. The incremental analysis feature seems to have been phased out, and issues ana ...

A missing definition for req.body.object

The issue with the req.body.object variable persists. Even though I have body parser imported, the value remains undefined when I try to console.log() it. //javascript const express = require('express'); var bodyParser = require('body-pa ...

What are the Javascript Keycodes for the letter 'a' - is it 65 or

I am currently working with JavaScript on my MacBook Pro running OSX 10.11.x, using the Chrome browser. The function I am using is: window.onkeypress = function(e) { var key = e.keyCode ? e.keyCode : e.which; console.log("keypressed = " + key); } ...

The module 'file-name.png' and its corresponding type declarations are not found in typescript react

I'm attempting to import a png file into my TypeScript React project using the following syntax: import logo from 'assets/Logo.svg'; However, I am encountering this TS error: Cannot find module 'assets/Logo.svg' or its corresp ...

How can you ensure the dynamic search parameter is accurately configured within the URL?

**Is the dynamic search parameter correctly set in the URL? Should I be using backticks or other syntax? I want to search for objects within a backend URL endpoint based on user input. https://codesandbox.io/s/onscroll-izfjoc?file=/index.html** people: ...

What is the correct way to type this object conversion?

I'm trying to ensure type safety for a specific converting scenario. The goal is to map over the palette object and convert any entries to key-value pairs, similar to how tailwindcss handles color configurations. However, I am facing an issue where th ...

When attempting to embed Ruby code within JavaScript, Ruby is not being acknowledged or

I am facing an issue with accessing values of a hash created by a ruby function inside javascript. This is the code snippet from my controller: class TransferController < ApplicationController def index require 'json' #@t ...

JavaScript saves all URLs using a consistent format (http, https, www.)

As a junior backend developer, my experience with JavaScript is limited. I am attempting to standardize the format of stored URLs as shown below: www.hello.com hello.com http://hello.com https://hello.com Currently, if I input hello.com, it automatically ...

ng-class will not activate a custom directive

I have developed a custom AngularJS directive that should work on elements with the specified class name .collapse. However, when I apply this class using Angular's ng-class directive, the custom collapse directive does not get activated. Here is a ...