Enhancements to managing universal configuration object across the entire application

My current project involves working on an application with multiple products. To streamline product-specific configuration and eliminate the need for excessive if-else statements, I am looking to implement product-specific config keys that are consistently maintained across all products. The use of interfaces will ensure that developers do not overlook any key when adding it to a product.

I seek suggestions on the following points:

  1. In anticipation of potential size increases in the object, I aim to dynamically import objects based on the current product-name (product1 | product2, etc.) to enhance overall performance.

  2. Suggestions for improving the structure of the ProductConfigService class.

  3. Explore efficient alternatives or approaches leveraging TypeScript (TS).

Your input is appreciated.

interface PRODUCT_CONFIG {
    API_KEY: string,
    AGE: number,
    TEXT: string

}

const product1: PRODUCT_CONFIG = {
    API_KEY: "SOME_VALUE",
    AGE: 10,
    TEXT: "SOME_VALUE"
}


const product2: PRODUCT_CONFIG = {
    API_KEY: "SOME_VALUE"
    AGE: 12,
    TEXT: "SOME_VALUE"
}


class ProductConfigService {

    private product: PRODUCT_CONFIG;
    

    constructor(private accessKey:string) {
      this.product = product2; // should be dynamic based on the current selected application. This is hard-coded to product2.
    }

    getConfig(): string {
      //@ts-ignore
      return this.product[this.accessKey];
    }

}

// consumer.

let product = new ProductConfigService('AGE');

console.log(product.getConfig());

Answer №1

I propose the creation of an abstract class that can be inherited to cater to the specific needs of any application.


By default, there will be a PRODUCT_CONFIG that can also be extended as needed.

In the code snippet below, the getConfig() function is designed to return the appropriate value based on the configured key.


However, there is a downside: users of the ProductConfigService class must manually specify the name of the key used for configuration. It's a challenge to extract it from the parameter itself.


Check out the interactive playground


// ---------- ABSTRACT CLASS DECLARATION

interface PRODUCT_CONFIG {
    API_KEY: string;
    AGE: number;
    TEXT: string;
}

abstract class AProductConfigService<T extends PRODUCT_CONFIG, U extends keyof T> {
    protected product: T;

    protected accessKey: keyof T;
    
    constructor(accessKey: keyof T, product: T) {
      this.accessKey = accessKey
      this.product = product;
    }

    public getConfig(): T[U] {
      return this.product[this.accessKey] as T[U];
    }
}

// ---------- CLASS IMPLEMENTATION

interface EXTENDED_PRODUCT_CONFIG extends PRODUCT_CONFIG {
    // additional keys ...
    ANIMAL: string;
}

class ProductConfigService<U extends keyof EXTENDED_PRODUCT_CONFIG> extends AProductConfigService<EXTENDED_PRODUCT_CONFIG, U> {
    constructor(accessKey: U) {
      super(accessKey, product2);
    }

    // ... new methods
}

// ---------- PRODUCTS DEFINITION

const product1: PRODUCT_CONFIG = {
    API_KEY: 'SOME_VALUE',
    AGE: 10,
    TEXT: 'SOME_VALUE',
}

const product2: EXTENDED_PRODUCT_CONFIG = {
    API_KEY: 'SOME_VALUE',
    AGE: 12,
    TEXT: 'SOME_VALUE',
    ANIMAL: 'fox',
}

// -------------- PRODUCT USE

const productA = new ProductConfigService<'AGE'>('AGE');

const valA = productA.getConfig();

console.log(valA);

const productB = new ProductConfigService<'API_KEY'>('API_KEY');

const valB = productB.getConfig();

console.log(valB);

const productC = new ProductConfigService<'ANIMAL'>('ANIMAL');

const valC = productC.getConfig();

console.log(valC);

// ----------------

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

The rsuite table does not properly reflect changes in state data

This is the render method that I am working on render() { return ( <Contentbox> <ol> {this.state.data.map((obj) => ( <li key={obj._id}>{obj.name}</li> ) ...

How is it possible for a JavaScript variable sharing the same name as a div Id to automatically pass the div?

This is just ridiculous. Provided HTML <p id = "sampleText"></p> Javascript var sampleText = "Hello World!"; Execution console.log(sampleText); // prints <p id = "sampleText"></p> How is this even possible? I ...

Challenging Trigonometry Puzzles in Javascript

In my project, I am creating an interactive application where a group of humans and bacteria engage in a game of chase. However, I encountered a problem where instead of moving directly towards their target, all entities would veer to the left. I attempt ...

Getter and setter methods in Angular Typescript are returning undefined values

I am facing a challenge in my Angular project where I need a property within a class to return specific fields in an object. Although I have implemented this successfully in .Net before, I am encountering an issue with getting an "Undefined" value returned ...

Error: The function SomeFunction is not recognized as a valid function (Mongoose library)

Help needed! I'm encountering an error stating "TypeError: User.getUserByUsername is not a function at Strategy._verify (.../routes/users.js:65:10) var User = require('../models/user'); passport.use(new LocalStrategy( function(username, ...

Navigating the use of property annotations in Mapped Types with remapped keys

After exploring the concept of Key Remapping in TypeScript, as shown in this guide, I am wondering if there is a way to automatically inherit property annotations from the original Type? type Prefix<Type, str extends string> = { [Property in keyo ...

What is the best way to make an array with values from a checkbox list?

I am working on a project that involves rendering a list of products categorized into different categories. Users can select these categories using checkboxes. Are you interested in learning how to create an array containing the selected values from the ch ...

Switching from Vue's Options API to Composition API is like transforming your code from

My goal is to transition the code below from using the options API to the composition API in Vue while utilizing Typescript. data() { return { items: [ 'Car', 'Truck', 'Bike', 'Ca ...

Error 404 encountered when attempting to refresh a Single Page Application built with React Router on GitHub Pages

My website was created using React and React Router, hosted on Github Pages. Whenever I try to refresh a page that isn't the home page or open a new tab using ctrl+click, I encounter a 404 error. This is because Github Pages doesn't support front ...

Is OnPush Change Detection failing to detect state changes?

Curious about the issue with the OnPush change detection strategy not functioning properly in this demonstration. My understanding is that OnPush change detection should activate when a property reference changes. To ensure this, a new array must be set e ...

When using TypeScript, default imports can only be done with the 'esModuleInterop' flag enabled

Below is my current code snippet in index.ts: import { User } from "./datatypes" import express from 'express'; console.log("hello world") Displayed is the content of my package.json: { "name": "simple_app& ...

Refresh the view when the URL is modified

Utilizing angularjs alongside ui-router (using the helper stateHelperProvider) to organize views and controllers on the page. Encountering an issue where the views are not updating as expected. The relevant code snippet config.js app.config(function($h ...

Wrapper around union function in TypeScript with generics

I'm struggling to find a solution for typing a wrapper function. My goal is to enhance a form control's onChange callback by adding a console.log. Can someone please point out what I might be overlooking? interface TextInput { type: 'Tex ...

Step-by-step guide on setting up a click counter that securely stores data in a text file, even after the

Can anyone help me make this link actually function as intended? Right now it only runs the JavaScript code, but I would like it to run the code and redirect to a webpage. Additionally, I need the data to be saved to a text file. Please provide assistanc ...

What is the process for javascript selecting a remote-data service?

I recently purchased a new app and am diving into Javascript and AngularJS for the first time. As I try to navigate through the code, I find myself puzzled by how the function in homeService.js is able to utilize remote-data.service.js. Featured below is ...

The function "onClick" within an external .js file is being referenced

Just starting to learn Javascript and experimenting with an onClick event for an image in an external .js file using the HTML tag. <script type="text/javascript" src="embed.js"> The code found in "embed.js" is as follows: var image1=new Image(); i ...

What is the unit testing framework for TypeScript/JavaScript that closely resembles the API of JUnit?

I am in the process of transferring a large number of JUnit tests to test TypeScript code on Node.js. While I understand that annotations are still an experimental feature in TypeScript/JavaScript, my goal is to utilize the familiar @Before, @Test, and @Af ...

On-page refresh triggering HTTP 404 error in Vue3 routing situation

Issue Upon reloading a route, such as /installer, in Vue3.js, I encounter the following error: https://i.sstatic.net/UKxdk.png Code Snippet I am utilizing the Router with the setup below: const router = createRouter({ history: createWebHistory(proces ...

Assign a class to an Angular component's host element without any conditions

In my Angular project, I have a component where I need to apply a class unconditionally. To achieve this, the host property within the @Component decorator can be used: import { Component } from '@angular/core'; @Component({ selector: 'ap ...

Issue with timebox filtering in customapp.js for Rally SDK 2

I am interested in creating a timebox filtered app and found an example at However, when attempting to run this on a custom HTML page, I encountered the following error: Failed to load resource: the server responded with a status of 404 (Not Found) on th ...