Using Typescript to create an index signature for easily accessing child objects through a proxy

As I am just starting to learn Typescript, please excuse me if this question is not well-formed.

I have an object (Object A) that encapsulates another object (Object B) and includes some methods to manipulate Object B. My goal is to proxy the access on Object A so when accessing a key, the corresponding value from Object B will be returned. To illustrate, consider the following code snippet:


type AType = {
  state: StateType
  doubleSomeVal(): number;
} & StateType

type StateType = {
   someVal: number;
}


type StateTypeKey = "someVal"

class A implements AType {
    state: StateType;

    doubleSomeVal() {
      return this.state.someVal * 2;
    }

    constructor(state: StateType) {
      this.state = state;
    }

    static create(state: StateType) {
      return new Proxy(new A(state), { 
        get(target: A, key: StateTypeKey) {
          return target.state[key] || target[key];
        }
     });
    }
} 

However, TypeScript raises an error because it does not recognize that my class A possesses the properties of StateType - which is understandable, but I would like to address this issue if possible.

Answer №1

I believe that you may not want A to implement AType, as it is only the outcome of A.create() that accomplishes that. Therefore, I would suggest modifying your A class in the following way:

class A {
  state: StateType;

  doubleSomeVal() {
    return this.state.someVal * 2;
  }

  constructor(state: StateType) {
    this.state = state;
  }

  static create(state: StateType) {
    return new Proxy(new A(state) as A & A["state"], {
      get(target, key) {
        return Reflect.has(target.state, key)
          ? Reflect.get(target.state, key)
          : Reflect.get(target, key);
      }
    });
  }
}

It's important to note that the target of the Proxy is asserted to be A & A["state"], which is essentially equivalent to AType. This assertion is required somewhere since the compiler cannot easily confirm that the proxy will behave as that intersection. The implementation of the get handler was also adjusted to enhance compatibility with the compiler and handle potential falsy values for target.state[key]. But the core idea remains the same.

Subsequently, you can utilize it like this:

const a = A.create({ someVal: 4 });
console.log(a.state); // {someVal: 4}
console.log(a.someVal); // 4
console.log(a.doubleSomeVal()); // 8

The code compiles successfully and produces the desired results. Best of luck!

Link to code

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

Converting the following ngRx selector to a boolean return – a guide

I am currently using the following filter to retrieve a list of data within a specific date range. I have implemented logic in the component where I check the length of the list and assign True or False to a variable based on that. I am wondering if ther ...

Error message in Angular 2: "__generator is not recognized"

I've been working on intercepting outgoing HTTP requests in Angular 2 in order to generate a token from the request body and attach it to the header of each post request. Below is the code snippet that I've implemented. Initially, I encountered ...

Dealing with React and Firebase Authentication Errors: How to Handle Errors for Existing Accounts with Different Credentials

According to the documentation at https://firebase.google.com/docs/auth/web/google-signin#expandable-1, when error.code === 'auth/account-exists-with-different-credential', signInWithPopup() should return an error.email. However, in my specific c ...

TS2339: The specified property is not present on the Angular type

Hey everyone, I've recently embarked on my Angular learning journey. Unfortunately, I'm currently facing this Error: 32 this.warning.error.push(entry.name+': '+entry.error); ~~~~~ src/app/dashboard/dashboard.component ...

React 16 exhibiting unexpected behavior with class names

I am trying to implement the classnames object into my input field within a react 16 project, completely independent of the webpack tool. const fieldClassName = classnames( formControlStyles.field, 'form-control' ) The 'form-control& ...

Angular 2 does not automatically re-evaluate *ngIf on model change

I am working on a navigation bar that consists of 2 buttons. My goal is to display only the button for the other page and disable the button for the current page. Currently, when I navigate to the settings page, the settings button is hidden. However, whe ...

The @Input directive is not compatible with the OnPush change detection strategy

page.html <app-parcel-delivery-cost-promo [parcelDeliveryCost]="parcelDeliveryCost"> </app-parcel-delivery-cost-promo> page.ts changeDetection: ChangeDetectionStrategy.OnPush, parcelDeliveryCost: Partial<ParcelDeliveryCostModel>; ...

Is it possible to convert several XLIFF files of different languages into JSON files using Angular?

I was looking to create a universal logic in a single XLIFF build that would allow access to all languages through JSON files. My goal was to find a way for the code to efficiently load multiple translations within one XLIFF build and execute these transl ...

What is the best way to map elements when passing props as well?

In my code, I am using multiple text fields and I want to simplify the process by mapping them instead of duplicating the code. The challenge I'm facing is that these textfields also require elements from the constructor props. import React, { Compon ...

Struggling to bring in components in ReactJS

My journey with ReactJS has just begun, and I've encountered some issues with the code that I believe should work but doesn't. To start off, I set up a new ReactJS project using the npm command create-react-app. Following this, I installed Googl ...

Angular encountered an ERROR of type TypeError where it cannot access properties that are undefined when trying to read the 'title'

I designed a form and I am trying to save the information entered. However, when I attempt to use the save method, an error keeps popping up. How can I troubleshoot this issue and successfully save the data from the form? ...

Dynamic form groups in Angular: Avoiding the issue of form inputs not binding to form groups

Purpose My goal is to develop a dynamic form in Angular that adjusts its fields based on an array received from the backend. For example, if the array contains ["one", "two", "three", "four"], the form should only ...

An assortment of diverse data types in TypeScript arrays

Considering adding type to my existing API, I have a function that can accept a string, function, or object (utilizing overloading). However, it is also able to accept an array of mixed values. Is there a way to have an Array in TypeScript that consists o ...

What is the best way to develop a function that can take in either a promise or a value and output the same type as the input parameter?

I'm currently working on a TypeScript function that can handle either an A type or a Promise<A>. In this case, A represents a specific concrete type, and the function should return the same type. If it receives a Promise<A>, then the retur ...

Steps to resolve the error "The value for '--target' option should be one of the following: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es201', 'esnext'."

I recently cloned an Angular application and encountered an error related to the "target" property in the tsconfig.json file within Visual Studio 2019. My Angular version is v16.1.4, with Typescript v5.1.6. I've attempted to resolve this issue by upda ...

Having trouble viewing the initial value in an AngularJS2 inputText field

I'm having trouble displaying the initial value in inputText. I'm unsure of what mistake I'm making, but the value should be showing up as expected. Kind regards, Alper <input type="text" value="1" [(ngModel)]="Input.VSAT_input1" name= ...

I am looking to implement tab navigation for page switching in my project, which is built with react-redux and react-router

Explore the Material-UI Tabs component here Currently, I am implementing a React application with Redux. My goal is to utilize a panelTab from Material UI in order to navigate between different React pages. Whenever a tab is clicked, <TabPanel value ...

Integrating JavaScript functions into TypeScript

When converting a JavaScript function to TypeScript, I encountered an issue. The function works fine in JS but in TS, I receive the following error: [ts] Cannot find name 'PasscodeAuth'. Did you mean 'passcodeAuth'? function passco ...

Retrieving values from a nested array within a JSON object

When making a GET request, the JSON object returned has this structure: {"ID":5176, "DateFrom":"8/29/2018", "DateTo":"8/29/2018", "Units":[{"Key":"Value","Key2": "Value2"}] } The issue is with accessing the value of Units[0]. I've attempted the foll ...

Is there a way for me to transfer a variable to a URL?

I'm attempting to send an email that includes a link with a value obtained from Firebase. While I can successfully retrieve the value, I am unsure how to add it to the existing link. Here is my code snippet: sendinvite() { var user = firebase.a ...