Leveraging private members in Typescript with Module Augmentation

Recently, I delved into the concept of Module Augmentation in Typescript. My goal was to create a module that could inject a method into an object prototype (specifically a class) from another module upon import.

Here is the structure of my folders:

.
├── DynamicAdvertising
│   ├── asTemporalSlots.ts
│   └── index.ts
└── index.ts

I wanted to achieve the following functionality:

import Personalisation from "./DynamicAdvertising";
/** Here Personalisation should not have the method 'asTemporalSlots' **/
import "./DynamicAdvertising/asTemporalSlots";
/** Here Personalisation should have it **/

The Personalisation class had the following setup:

export default class Personalisation {
    constructor(private response: Response) {}

    static async fetch(request: PersonalisationRequest<any>) {
        if (!(request instanceof PersonalisationRequest)) {
            throw new Error('Wrong request. Cannot proceed.');
        }

        const response = await fetch(request);
        return new Personalisation(response);
    }
    /* ... */
}

Creating an instance through a static method was the approach taken. To extend Personalisation in asTemporalSlots, I followed this pattern:

import Personalisation from ".";

declare module "." {
    export default interface Personalisation {
        asTemporalSlots(this: Personalisation): any
    }
}

Personalisation.prototype.asTemporalSlots = async function asTemporalSlots(): AdvSlots[] {
    ...
}

While extending worked without issues, accessing the this.response property, which was marked as private, posed a challenge when using the extended method. When directly adding asTemporalSlots to Personalisation, it could be used without any problems. The question arises - why does extending the prototype cause issues with private properties? How can this be resolved while keeping the response private?

Grateful for any insights and suggestions. Thank you!

Answer №1

If you want to maintain type checking on the response, you can utilize string indexing:

Personalisation.prototype.asTemporalSlots = async function asTemporalSlots() {
    let a = await this.response.json(); // <- error not accessible
    let b = await this["response"].json(); // <- ok
};

When accessing a class field via string indexing, Typescript does not verify the modifiers on it. This method works because a class instance is essentially an object with a predetermined prototype, and there are no private class members in javascript.

Alternatively, you can use as any to bypass type checking on response:

Personalisation.prototype.asTemporalSlots = async function asTemporalSlots() {
    let c = (this as any).response.json();
};

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

Utilizing Conditional Aurelia Validation Based on Element's Display Status

Currently, I am in the process of setting up a license subscription form using Aurelia and the Aurelia Validation plugin. Within this form, there is a fieldset dedicated to personal information which contains mostly required fields that are validated by Au ...

Troubleshooting d3js Type Errors in Angular (Updated Version)

Encountering numerous type errors with d3js when integrating it into Angular (typescript). svg.call(d3.zoom().on('zoom', () => { g.attr('transform', d3.events.transform); })); Error thrown: S2345: Argument of type 'Zo ...

Option to modify the arguments of a method in a parent class

I encountered an interesting problem recently. I have two classes: class Animal { public talk() { console.log('...'); } } and class Dog extends Animal { public talk(noise: string) { console.log(noise); super.talk() } } The i ...

What is the step-by-step process for incorporating the `module` module into a Vue project?

ERROR Compilation failed with 6 errors 16:20:36 This specific dependency could not be located: * module in ./node_modules/@eslint/ ...

How to extract a JavaScript object from an array using a specific field

When dealing with an array of objects, my goal is to choose the object that has the highest value in one of its fields. I understand how to select the value itself: Math.max.apply(Math, list.map(function (o) { return o.DisplayAQI; })) ... but I am unsur ...

Shifting attention to an angular 6 form field

I am developing an application in Angular which involves creating, reading, updating, and deleting user information. I have a requirement for the username to be unique and need to display an error message if it is not unique, while also focusing on the use ...

Ways to verify if a value corresponds to a particular data type

Is there a more elegant way for TypeScript to check if a value matches a specific type without actually invoking it, instead of the method described below? Consider the following example: import { OdbEventProcessorFunc } from "./OdbEventProcessor&quo ...

Increase the timestamp in Typescript by one hour

Is there a way to extend a timestamp by 1 hour? For instance, 1574620200000 (Including Microseconds) This is my date in timestamp format. How can I add a value to the timestamp to increase the time by an additional hour? ...

The value from select2 dropdown does not get populated in my article in Angular

I am attempting to link the selected value in a dropdown menu to an article, with a property that matches the type of the dropdown's data source. However, despite logging my article object, the property intended to hold the selected dropdown value app ...

Error message appears when using TypeScript with a React Material table showing a generic type error

I am currently attempting to implement react-material in a Typescript project. As a newcomer to Typescript, I am encountering some errors that I am unsure how to resolve. In this gist, I am trying to create a reusable React component (Please view the gis ...

Is it possible to display the combined string when concatenating two strings?

Consider the following code snippet: const a = "url"; const b = "/route"; const c = a + b; Even though TypeScript knows the exact values of a and b, resulting in immutable constants, when concatenating both strings, the type of c is di ...

Combine the object with TypeScript

Within my Angular application, the data is structured as follows: forEachArrayOne = [ { id: 1, name: "userOne" }, { id: 2, name: "userTwo" }, { id: 3, name: "userThree" } ] forEachArrayTwo = [ { id: 1, name: "userFour" }, { id: ...

Troubleshooting connectivity problems: SocketIO integration with microservices on a Kubernetes platform

I have organized my system using microservices architecture, with separate services for client interactions, orders, payments, and more. Each of these services runs on its own express server. Now, I am looking to integrate real-time feedback functionality ...

Discover more efficient methods for utilizing generics in hierarchical objects within typescript

How can I optimize the structure of an object that contains nested objects in Typescript to minimize type repetitions? type itemType = { [key: string]: { [key: string]: { [key: string]: { [key: string]: string } }; }; }; ...

Angular is throwing a RangeError due to exceeding the maximum call stack size

Encountering a stackOverflow error in my Angular app. (see updates at the end) The main issue lies within my component structure, which consists of two components: the equipment component with equipment information and the socket component displaying conn ...

The KeyValuePair<string, Date> type in Typescript cannot be assigned to the KeyValuePair<number, string> type

I encountered the following issue: An error occurred stating that Type 'KeyValuePair<string, Date>' is not assignable to type 'KeyValuePair<number, string>'. Also, it mentioned that Type 'string' is not assignab ...

What steps should I take to verify the validity of an Angular form?

I am struggling with validating an inscription form in HTML. Despite trying to implement validations, the inputs are still being saved in the database even when they are empty. Here are the validations I want to include: All inputs are required Email addr ...

Showing the outcome of the request from the backend on an HTML page using the MEAN stack

I am currently in the process of developing an angular application with a node.js + express backend. After successfully retrieving the necessary data from MongoDB and being able to view it through terminal, I encountered a challenge when trying to display ...

Steps for generating a unit test for code that invokes scrollIntoView on an HTML element

I'm currently working on an Angular component where I have a method that involves scrolling through a list of elements known as "cards" based on certain criteria. Despite my efforts to write unit tests for this method using the Jasmine framework, I&ap ...

Utilize nested object models as parameters in TypeScript requests

Trying to pass request parameters using model structure in typescript. It works fine for non-nested objects, but encountering issues with nested arrays as shown below: export class exampleModel{ products: [ { name: string, ...