Breaking Down a Sizeable TypeScript Class Without Altering Its API

Suppose I have enhanced the CRM FormContext by creating a new TS class that wraps it and adds helper functions. This new ExtendedContext includes functions like getDisplayValue(attName), which retrieves the attribute, handles cases where it's not on the form, identifies the attribute type, and returns the appropriate "displayed value". As I continue to add more helper functions, the class becomes larger and larger, necessitating splitting it into multiple classes. However, I want to avoid changing the API. The consuming code should not be required to create a separate DisplayExtendedContext class to utilize getDisplayValue; all functions should remain within the main extended context. What is the best approach to tackle this?

The current approach feels cumbersome and appears as follows:

// extendedContex.ts
import { DisplayContext } from "../context/display";

export class ExtendedContext implements XrmExt.ExtendedContext {
  public context: Xrm.FormContext // Actual Xrm.Client form context
  private display: DisplayContext;
  
  constructor(context: Xrm.FormContext){
    this.context = context;
    this.display = new DisplayContext(this);
  }
  
  public getDisplayValue(att: string): string {
    return display.getDisplayValue(att);
  }
}

// xrmExt.d.ts
declare namespace XrmExt {
    interface ExtendedContext {
        getDisplayValue(att: string): string;
    }
}

// ../context/display.ts
export class DisplayContext {
    private context: XrmExt.ExtendedContext;
    
    constructor(context: XrmExt.ExtendedContext){
        this.context = context;
    }
    
    public getDisplayValue(att: string): string {
        // Implement logic here, with full access to the ExtendedContext
    }
}

Here are the issues encountered:

  1. I find myself duplicating pass-throughs for ExtendedContext functions. For each function added, I must implement it in the smaller context class, include it as a pass-through in the ExtendedContext class, and update the ExtendedContext interface. This repetitive task is tedious, and I seek an alternative solution.
  2. Although minor, the ExtendedContext passed to the DisplayContext is not fully-initialized, potentially leading to null reference errors. If the DisplayContext were to invoke a function on the XrmExt.ExtendedContext interface within its constructor that it also implements, the class-level "display" field of the ExtendedContext class may not be populated, resulting in a null reference exception. An unwritten rule of never accessing the ExendedContext from a smaller class constructor could prevent this issue from arising. I am considering Mixings as a possible way forward, but unsure if it's the right direction. Any thoughts or suggestions?

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

Troubleshooting TypeScript import problems within apollo-server-express, apollo-server, and apollo-cache-control

Currently, I am in the process of upgrading from "apollo-server": "^2.9.4" and "apollo-server-express": "^2.9.4 to version 2.12.0 in my Typescript project. However, while building the application, I encountered the following error: node_modules/apollo ...

Issue with Component in Angular not functioning properly with proxy construct trap

Currently working with Angular 17, I have a straightforward decorator that wraps the target with Proxy and a basic Angular component: function proxyDecorator(target: any) { return new Proxy(target, { construct(target: any, argArray: any[], newTarget: ...

Error message in Angular: Unable to locate a differ that supports the object '[object Object]' of type 'object.' NgFor is only able to bind to iterables like Arrays

When making an API call in my Angular project, I receive the following JSON response: { "data": { "success": true, "historical": true, "date": "2022-01-01", "base": "MXN&quo ...

Rearrange the provided string in a particular manner

Looking to transform a string like '12:13:45.123 UTC Sun Oct 17 2021' into 'Sun Oct 17 2021 12:13:45.123 UTC' without calling slice twice. Is there a more elegant and efficient way to achieve this? Currently using: str.slice(18)+&apo ...

Update the data and paginator status

In my development project, I have implemented PrimeNG Turbotable with the code <p-table #dt. Based on information from here, using dt.reset() will clear the sort, filter, and paginator settings. However, I am looking for a solution to only reset the pa ...

Using Angular2's NgFor Directive in Components

I am faced with the challenge of converting a tree-like structure into a list by utilizing components and subcomponents in Angular 2. var data = [ {id:"1", children: [ {id:"2", children: [ {id: "3"}, {id: "3"}, {i ...

Angular 5 Image Upload - Transfer your images with ease

I am having trouble saving a simple post in firebase, especially with the image included. This is my current service implementation: uploadAndSave(item: any) { let post = { $key: item.key, title: item.title, description: item.description, url: '&a ...

Guide on leveraging the `ConstructorParameter` tool with generic-friendly types

Attempting to extract the constructor parameter type from a class, but the class in question accepts a generic type value. Does anyone know how to achieve this? Encountered error: ConstructorParameters<typeof(DictionaryClass<contentType>)[0]; ...

Constructor polymorphism in TypeScript allows for the creation of multiple constructor signatures

Consider this straightforward hierarchy of classes : class Vehicle {} class Car extends Vehicle { wheels: Number constructor(wheels: Number) { super() this.wheels = wheels } } I am looking to store a constructor type that ext ...

typescript: Imported modules in typescript are not functioning

I'm facing an issue where I installed the 'web-request' module but unable to get it working properly. Here is my code: npm install web-request After installation, I imported and used it in my class: import * as WebRequest from 'web-r ...

What is the best way to manage a promise in Jest?

I am encountering an issue at this particular section of my code. The error message reads: Received promise resolved instead of rejected. I'm uncertain about how to address this problem, could someone provide assistance? it("should not create a m ...

Struggles with deducing argument types in Typescript

I'm struggling to comprehend an inference error. The ts linter highlights (event: E) within useCallback with the following message. When I cast the callback of useCallback with as T, the linter message disappears. Is there a way to avoid this workarou ...

Transforming the Material UI v5 Appbar theme upon opening a dialog box

My layout consists of an AppBar, Drawer, and the page content. Within the content, there is a Dialog that opens when a user clicks on a button. https://i.sstatic.net/5Rlno.png Interestingly, when the dialog is open, the color of the AppBar changes to whi ...

Determine the data type of a class property by referencing the data type of a different property within the

Why am I getting an error when assigning to this.propertyB in TypeScript? class Example { public readonly propertyA: boolean; private readonly propertyB: this['propertyA'] extends true ? null : 'value'; public constructor() ...

The DAT GUI controls are mysteriously absent from the scene

Within a modal, I have set up a threejs scene with three point lights. All functions are exported from a separate file called three.ts to the modal component. The issue I am facing is that when I try to initialize DAT.GUI controls, they end up rendering ...

Achieving seamless integration among react-templates, TypeScript, and webpack

I am attempting to integrate TypeScript, react-templates, and webpack for a seamless workflow. My starting point was the sample code provided at https://www.typescriptlang.org/docs/handbook/react-&-webpack.html. The configuration in the webpack.config ...

Tips for incorporating Angular2 into Eclipse using TypeScript

Recently, I delved into the world of Angular 2 and noticed that TypeScript is highly recommended over JavaScript. Intrigued by this recommendation, I decided to make the switch as well. I came across a helpful guide for setting up everything in Eclipse - f ...

Display a loading indicator with the shortest possible delay whenever utilizing the React Router v6 Link functionality

Integrate React and Router v6 App.tsx: const Page1 = lazy(() => pMinDelay(import('./views/Page1'), 500)) const Page2 = lazy(() => pMinDelay(import('./views/Page2'), 500)) return ( <Suspense fallback={<Loading/>}gt ...

The Javascript Node class encountered an error: X has not been defined

I have a class that looks like this: const MongoClient = require("mongodb").MongoClient; const ConnectionDetails = require("./ConnectionDetails").ConnectionDetails; const Recipe = require("./recipe").Recipe; var ObjectId = req ...

Ways to categorize axios call headers

I'm encountering an issue while attempting to send a request via Axios and specifying request headers using types. Unfortunately, I am running into an error. To address this, I have defined an interface called Headers and utilized it to declare a var ...