Using ES6 proxy to intercept ES6 getter functions

I have implemented a proxy to track all property access on instances of a class, demonstrated in the code snippet below:

class Person {
  public ageNow: number;

  public constructor(ageNow: number) {
    this.ageNow = ageNow;

    const proxy = new Proxy(this, {
      get: (target, property) => {
        console.log(property);
        return target[property as keyof typeof target];
      },
    });
    return proxy;
  }

  public ageIn10Years1() {return this.ageNow + 10;}
  public get ageIn10Years2() {return this.ageNow + 10;}
}

When I create an instance and call a method like:

const peter = new Person(18);
console.log(peter.ageIn10Years1());

it logs 'ageInYears1', 'ageNow', and 28 (in that order), which aligns with my expectations.

However, when I use a getter like:

console.log(peter.ageIn10Years2);

which also prints 'ageInYears2' and 28 but not 'ageNow', even though this property is being accessed.

What could be causing this behavior and how can it be resolved?

Answer №1

Instead of accessing the proxy you created, the getter retrieves data from the original object.

To address this issue, consider invoking the getter function on the proxy itself.


class Person {
  public ageNow: number;

  public constructor(ageNow: number) {
    this.ageNow = ageNow;
    const proxy = new Proxy(this, {
      get: (target, property) => {
        const descriptor = Object.getOwnPropertyDescriptor(Person.prototype, property);
        if (descriptor && typeof descriptor.get === 'function') {
            console.log("calling",property);
          return descriptor.get.call(proxy);
        } else {
          console.log(property);
          return target[property as keyof typeof target];
        }
      },
    });
    return proxy;
  }

  public ageIn10Years1() {return this.ageNow + 10;}
  public get ageIn10Years2() {return this.ageNow + 10;}
}

const peter = new Person(18);
console.log(peter.ageIn10Years1());
console.log(peter.ageIn10Years2);

Answer №2

The issue stems from the functionality of this.

When calling your method in the initial scenario with peter.ageIn10Years1(), this refers to peter, acting as a proxy. This explains why all values are properly proxified.

You can confirm this by binding your ageIn10Year1 method:

class Person {
  constructor(ageNow) {
    this.ageNow = ageNow;

    this.ageIn10Years1 = this.ageIn10Years1.bind(this);

    const proxy = new Proxy(this, {
      get(target, property, receiver) {
        console.log(property)
        return target[property];
      },
    });
    return proxy;
  }

  ageIn10Years1() {
    return this.ageNow + 10;
  }
  getAgeIn10Years2() {
    return this.ageNow + 10;
  }
}

const peter = new Person(18);
console.log(peter.ageIn10Years1());

By making this call, it will function similarly to the previous one.


In the alternate case, leveraging a getter doesn't dynamically bind this, resulting in representation of the original object.

To resolve this dilemma, consider refraining from using getters as a straightforward solution.

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

How do I utilize the file handler to execute the flush method within the Deno log module using Typescript?

I'm having trouble accessing the fileHandler object from my logger in order to flush the buffer to the file. This is the program I am working with: import * as log from "https://deno.land/<a href="/cdn-cgi/l/email-protection" class="__cf_emai ...

What is the reason for not being able to access default props in the react constructor but being able to access them in the render method

Why is the initial this.props failing as suggested by the title? And how can you address this situation when you need to access props within your constructor, such as in scenarios involving subscriptions? class AboutBox extends Component { static defa ...

Specify the object key type when using a `for-in` loop

My current situation involves an object type: interface ShortUrlParam { openid: string; avatar: string; nickname: string; } const param: ShortUrlParam = { openid: 'abc123', avatar: '', nickname: 'wenzi&apo ...

Displaying data issue with Typescript typed array

While working with Angular 7 and Typescript 3, I encountered an issue where I was trying to pre-populate an array of ingredients in a service for use in a component. However, when I checked the console output, the array was showing empty objects. If I ini ...

activating serverless.yml for aws-xray

I have been attempting to implement AWS X-Ray for all lambda functions in the following manner: serverless.yml provider: tracing: lambda: true apiGateway: true name: aws runtime: nodejs8.10 stage: ${opt:stage, 'dev'} region: ...

Struggling to dynamically update array values by comparing two arrays

I am faced with a scenario where I have two arrays within an Angular framework. One of the arrays is a regular array named A, containing values such as ['Stock_Number', 'Model', 'Type', 'Bill_Number'] The other arr ...

Verify that the Angular service has been properly initialized

I am currently testing my Angular service using Karma-Jasmine and I need to verify that the loadApp function is called after the service has been initialized. What would be the most effective approach for testing this? import { Injectable, NgZone } from ...

Unable to generate paths in Ionic 3

I am trying to view the actual route on the URL, but I'm having trouble figuring out exactly what needs to be changed. I've been referring to the documentation at: https://ionicframework.com/docs/api/navigation/IonicPage/ However, I keep encoun ...

Conditionally typing in TypeScript to check if a string contains a specific value

Looking to create a function that takes a string as input and determines whether it contains '[]' or not. If it does, the function should return a list, otherwise an object. This is what I have so far: function customFunction<T = any>(input ...

Error occurred after attempting to make a GET request

What I aim to achieve: I need to send two parameters from the front-end to the back-end. This is the code snippet: In TypeScript file: activeFromActiveToQuery(req?: any): Observable<ResponseWrapper>{ const options = createRequestOption(req) ...

Hover shows no response

I'm having trouble with my hover effect. I want an element to only be visible when hovered over, but it's not working as expected. I've considered replacing the i tag with an a, and have also tried using both display: none and display: bloc ...

Issue NG1006: Class has two conflicting decorators applied

I encountered an issue while compiling my project: PS C:\Users\hasna\Downloads\A La Marocaine git - Copie\ALaMarocaineFinal\frontend\src\app> ng serve Compiling @angular/forms : es2015 as esm2015 An unhandled exc ...

Suggestions for efficiently filtering nested objects with multiple levels in RXJS within an Angular environment?

Just a Quick Query: Excuse me, I am new to Typescipt & RxJS. I have this JSON data: [ { "ID": "", "UEN": "", "Name": "", "Address": "", "Telephone&quo ...

Establishing a default value as undefined for a numeric data type in Typescript

I have a question regarding setting initial values and resetting number types in TypeScript. Initially, I had the following code snippet: interface FormPattern { id: string; name: string; email: string; age: number; } const AddUser = () => { ...

Visibility in classes can shift once a new file is imported

Currently, I am encountering a puzzling issue in my angular2 project using typescript. In my main.ts file, which contains a component along with some imports at the start of the file, there is a custom type class (let's call it TypeFoo) located in mod ...

Transform an array of Boolean values into a string array containing only the values that are true

Suppose we have an object like the following: likedFoods:{ pizza:true, pasta:false, steak:true, salad:false } We want to filter out the false values and convert it into a string array as shown below: compiledLikedFoods = ["pizza", "steak"] Is t ...

What is the best way to search for and isolate an array object within an array of objects using Javascript?

I am attempting to narrow down the list based on offerings const questions = [ { "id": 2616, "offerings": [{"code": "AA"},{"code": "AB"}]}, { "id": 1505, "offerings": [ ...

Hierarchy-based state forwarding within React components

As I embark on the journey of learning Typescript+React in a professional environment, transitioning from working with technologies like CoffeeScript, Backbone, and Marionettejs, a question arises regarding the best approach to managing hierarchical views ...

Can someone guide me on configuring Material-UI DataGrid in React to have multiple headers with column span?

Is there a way to achieve multiple headers with column span in the Material-UI DataGrid component? view image example ...

Customizing the file path for the PDF worker: A step-by-step guide

Incorporating the PDF Viewer Component from this source into an Angular 7 project has been a challenge. The documentation clearly states: The default worker is loaded from cdnjs.cloudflare.com. My goal is to load the worker from a local path within my ...