Leverage a TypeScript property descriptor to substitute the accessors without compromising on composability

Is there a way to create a TypeScript property descriptor that can override accessors and still be easily composed with other functionality?

Answer №1

The Decorators chapter in the TypeScript handbook suggests that achieving certain functionalities may be challenging or discouraged. According to the handbook...

...there is no current mechanism for describing an instance property when defining members of a prototype, and there isn't a way to observe or modify property initializers. Thus, a property decorator is limited to observing the declaration of a specific property name within a class.

However, my discovery of the `Object.getOwnPropertyDescriptor(target, key)` method seems promising in fulfilling these requirements.

Consider this code snippet as an example:

function decorator(name: string) {
    return function (target: any, key: string) {
        try {
            console.log(`${name}...`);
            let localValue = undefined;
            let prev = Object.getOwnPropertyDescriptor(target, key);
            let setter = function (newVal) {
                try {
                    console.log(`${name} setter(${newVal}) called...`);
                    if (prev) prev.set(newVal);
                    localValue = newVal;
                } finally {
                    console.log(`...${name} setter called`);
                }
            };
            let getter = function () {
                try {
                    console.log(`${name} getter(${localValue}) called...`);
                    if (prev) prev.get();
                    return localValue;
                } finally {
                    console.log(`...${name} getter called`);
                }
            };
            Object.defineProperty(target, key, {
                get: getter,
                set: setter,
                enumerable: prev == null ? true : prev.enumerable,
                configurable: prev == null ? true : prev.configurable
            });
        } finally {
            console.log(`...${name}`);
        }
    }
}

class MyClass {
    @decorator("decorator1")
    @decorator("decorator2")
    myProperty: string;
}

var mc = new MyClass();
mc.myProperty = "asdf";
console.log(mc.myProperty);

The output generated by the above script showcases the sequence of actions performed by each decorator.

decorator2...
...decorator2
decorator1...
...decorator1
decorator1 setter(asdf) called...
decorator2 setter(asdf) called...
...decorator2 setter called
...decorator1 setter called
decorator1 getter(asdf) called...
decorator2 getter(asdf) called...
...decorator2 getter called
...decorator1 getter called
asdf

I am uncertain whether this approach is optimal. Feedback and insights on this implementation are highly appreciated.

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

Failed to execute start script 'ng serve' in npm start

Let me make it clear: I'm brand new to AngularJS and pretty much any Web Technology. I consider myself a novice in the realm of Web Development. I attempted to install AngularJS, and truth be told, after numerous "Mysterious Button Clicks", I might ...

Retrieve component information from the service

Incorporated within my component is a form that I'm utilizing with reactive form and my intention is to reach this form through my service. For example: const id = MyComponent.id and inside my component: @Output: public id: number = 7; ...

TypeScript(error:2532): object may be undefined despite null or undefined check

Currently, I am developing a Discord-bot using TypeScript which includes a command to retrieve information from an airport. To do this, users only need to provide the 4-character ICAO code that identifies the specific airport. However, due to potential use ...

Tips for delivering a variable to a React Native Stylesheet

Is there a way to pass a variable to the "shadowColor" property in my stylesheet from an array declared in the code above? I keep encountering a "Can't find name" error. Attempting to use a template literal has not resolved the issue. Any assistance w ...

Avoid assigning an `any` value in an unsafe manner, especially when using a custom hook function

export const useSpecificHook = () => { return useContext(OurContext); }; export const useCustomProcessor = () => { const [notes, setNotes] = useState([]); const removeItems = () => { setItems([]); }; return { clearNotes, } ...

Accessing the form element in the HTML outside of the form tag in Angular 2

I am attempting to achieve the following: <span *ngIf="heroForm?.dirty"> FOO </span> <form *ngIf="active" (ngSubmit)="onSubmit()" #heroForm="ngForm"> <div class="form-group"> <label for="name">Name</label& ...

Can anyone assist me with creating a custom sorting pipe in Angular 2?

*ngFor="let match of virtual | groupby : 'gameid' I have this code snippet that uses a pipe to group by the 'gameid' field, which consists of numbers like 23342341. Now, I need help sorting this array in ascending order based on the g ...

Tips for transferring request variables/data from a middleware to another function in typescript

I need to authenticate a user's jwt token using middleware. This is the middleware I have: const authorized = (req: Request, res: Response, next: NextFunction) => { const token = req.header("token") if(!token){ return res.send("N ...

The mystery of the undefined return value in my Ionic v4 get function

I attempted to retrieve my location by saving the latitude and longitude, but my declared variable isn't returning anything. Take a look at my code snippet: public device_location: any = {}; constructor(private geolocation: Geolocation) { this.s ...

Declaring an array that holds Angular components in Angular 11: What's the best approach?

I'm trying to implement a feature in my Angular component where I can create a list that displays content from other components. My current approach involves declaring an array that contains references to different Angular components: import { Compone ...

Having trouble uploading a PNG image (logo) with Cypress

I have been attempting to upload a png file using Cypress and here is what I have tried so far: Cypress.Commands.add('upload_image', (fileName, selector) => { return cy.get(selector).then(subject => { return cy.fixture(fileName, &apo ...

Efficiently organizing items within a list on Ionic

Currently, I have an ion-list structured as follows: <ion-list *ngFor = "let chat of Chats"> <ion-item (click) = "openChat(chat.id)"> <ion-label> <h2> {{chat.username}} </h2> ...

Alter the value by clicking a button within the DynamicRadioGroupModel in ng Dynamic Forms

I am working with ng-dynamic-form (version 6.0.4) and NG Bootstrap in Angular 6. I have a simple question. When a button click event is triggered, I want to change the value in DynamicRadioGroupModel by using the "setValue()" method. However, I am facing ...

Refreshing the page after making an API call does not result in updated data

Within my VueJS application, I have implemented an API call to retrieve user statistics for display. The process involves a straightforward Java backend and utilizing an $axios get request. Upon initial page load, everything functions as anticipated. Howev ...

Error in NodeJS when trying to run ESM: "ReferenceError: exports is not defined

Having a tough time with this task. I'm attempting to execute ESM scripts on Node 14 (AWS Lambda) I am working on running this piece of code to convert 3D objects to THREE JSON. This involves using the command node -r esm fbx2three.js model.fbx. I ...

TypeScript and Next.js failing to properly verify function parameters/arguments

I'm currently tackling a project involving typescript & next.js, and I've run into an issue where function argument types aren't being checked as expected. Below is a snippet of code that illustrates the problem. Despite my expectation ...

Using SCSS based on the browser language in Angular: A Step-by-Step Guide

Is there a way to implement SCSS that is dependent on the user's browser language? When I checked, I found the browser language specified in <html lang = "de"> and in the CSS code as html[Attributes Style] {-webkit-locale: "en&quo ...

Sources of the TypeScript library in WebStorm

I'm brand new to TypeScript. I decided to use WebStorm because I'm familiar with JetBrains tools. In other programming languages, I'm used to having a workflow that includes some kind of dependency management system like Maven, which allows ...

Can you modify a specific column in a table using mat-table in Angular material?

For my project, I am utilizing Angular Material's table to present data in a tabular format. However, due to a new requirement, I now need to enable in-line editing for the last 2 columns alongside highlighting another column when the user clicks on t ...

An issue arises when trying to update state using useState in TypeScript

In our system, we have a state that contains an array of objects: interface Product { id: number; status: boolean; color: string; price: number; } const productList: Product[] = [ { id: 1, status: true, color: 'yellow', ...