Using Typescript file for importing configurations instead of relying on json files dynamically

Let me give you some context: Our team is working on creating AWS CDK modules using Typescript (just so you know, I'm not very experienced in TS).

One of the modules we're developing is for managing container-based applications that developers can use to set up their services. At a high level, each app's "definition" will look something like this:

import {containerApp} from 'CompanyContainerApp'
const environment = callSomeMethodToFindEnv() // for example, 'prod'
config = import('/prod')
const myApp = new containerApp(`myapp-${environment}`, config)

The challenge here is that 'prod' and 'dev' represent different config values that need to be passed to the constructor of containerApp. While I could use simple json files and parse them, these configs can get quite complex. Having them in a type would make it much easier to define which config attributes are required and which ones are optional.

Currently, this is what my code looks like:

// cat index.ts
import {Config} from './configdefinition'

export function hello(word: string = world): string {
    const envName = 'prod'
    const config: Config = import(`./${envName}`)
    return `Hello2 ${world}! `
}
hello()

// cat configdefinition.ts
export class Config {
    // properties with defaults
    readonly numberOfLegs: number = 8
    constructor(
        // required props
        readonly name: string,
        readonly lastname?: string
    ) {}
}

// cat prod.ts
import {Config} from './configdefinition'
const config = new Config(
    'prodman',
    'wakka'
)
export default config

Typescript is throwing an error saying that 'config' is a promise and not an instance of the Config class. I understand that this is a broad question, but I'm trying to figure out if this is even possible or if I should just stick to using old-school json for my configs (which wouldn't be ideal but it's doable).

At the moment, ts is complaining that my config constant is actually a promise, not an instance of the Confg class - it seems like using the import function will lead me into dealing with promises, which I was hoping to avoid.

So, in a nutshell: 1. Should I abandon the idea and go back to json-based configs? 2. If not, what would be the correct approach to dynamically importing another class instance while still enforcing "strong" types? (e.g., knowing that the config object is indeed an instance of Config)

I would greatly appreciate any guidance as I'm fairly new to Typescript.

UPDATE: A suggestion pointed me in the right direction, and I am now exploring the use of promises. Here's what I have come up with so far:

// cat configdefinition
export class Config {
    // properties with defaults
    readonly numberOfLegs: number = 8
    constructor(
        // required properties
        readonly name: string,
        readonly lastname?: string
    ) {}
}

// cat prod.ts
import {Config} from './configdefinition'
export const config: Config = new Config('Bobba', 'Fett')

//cat index.ts
import {Config} from './configdefinition'

export function doSomeStuff(config: any) {
    // @ts-ignore
    const thisConfig: Config = config.config
    console.log(thisConfig.lastname)
}

export function hello() {
    const envName = 'prod'
    const configImport: Promise<Config> = import(`./${envName}`)
    configImport.then(
        result => doSomeStuff(result)
    )
}
hello()

This solution works, although I had to use a ts-ignore to make Typescript recognize the dynamic extraction of the config attribute from the import. There may be better ways to achieve this without breaking the rules, but for now, I'm satisfied with this workaround. Hopefully, this helps someone facing similar challenges in the future.

Answer №1

This is how I got it to work:

Just made a small modification :

const configuration: Promise<Config> = import(`./${envName}`)

Here's the complete functioning code in a single module:

function greeting(term: string = 'world'): string {
    const envName = 'prod'
    const configuration: Promise<Config> = import(`./${envName}`)
    return `Hello2 ${term}! `
}
console.log(greeting());


// cat configdefinition.ts
 class Config {
    // properties initialized with default values
    readonly numberOfLegs: number = 8
    constructor(
        // mandatory properties
        readonly name: string,
        readonly lastname?: string
    ) {}
}


// cat prod.ts

const configuration = new Config(
    'prodman',
    'wakka'
);

An alternative way would be to utilize async and await like this:

async function greeting(term: string = 'world'): Promise<string> {
  const envName = 'prod'
  const configuration: Config = await import(`./${envName}`)
  return `Hello2 ${term}! `
}
console.log(greeting());

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

Handling click events on Datatable.net paging buttons

My goal is to capture the click event when one of the paging buttons on the Datatable is clicked in Angular. I'm not exactly sure how to go about accomplishing this! If I refer to this example, how can I adapt the code for Angular? Specifically, how ...

Attempting to simulate the behavior of Angular2 Token during testing

Currently, I am working on obtaining a token that is required for API authentication to retrieve a list. My approach begins with importing the angular2-token library: import { Angular2TokenService } from 'angular2-token'; After this, I include ...

Obtain a Spotify Token and showcase information in next.js

This is a Simple Next.js component designed to display the currently playing song on Spotify. Context: Utilizing app Router Due to Spotify's token requirements necessitating a server-side call, the entire request is made to fetch the song from an ...

The argument representing 'typeof Store' cannot be assigned to the parameter representing 'Store<AppState>'

I'm encountering an issue while trying to expand a service in Angular that utilizes ngrx. The error message I'm receiving is as follows: Argument of type 'typeof Store' is not assignable to parameter of type 'Store<AppState>& ...

Insert a new item into the array located within an Observable entity

In my angular application, I have a page where I am showcasing an object that contains an array of comments within it. This object is loaded into my class as an Observable and then displayed in the HTML using: <div class="container-fluid mt--7" ...

Transforming JavaScript to TypeScript in Angular: encountering error TS2683 stating that 'this' is implicitly of type 'any' due to lacking type annotation

While in the process of migrating my website to Angular, I encountered an error when attempting to compile the JS into TS for my navbar. After searching around, I found similar issues reported by other users, but their situations were not quite the same. ...

Tips for inserting a string into an array nested within an object stored in a state array

Currently, the variable sizeVariant is a string array and I am trying to append strings to it using an onClick event. The function findIndex seems to be working fine. However, there seems to be an issue with the concatenation section. It appears that using ...

Sending the id from a component to a service in Angular

In my current project, I am working on a chat application using Angular with WebSocket integration. Let me provide an overview of the architecture I have designed for this project. I created a module called 'chatting' which contains a list of use ...

Error: Unable to access properties from an undefined source while trying to read 'reRenderOnLangChange'

I encountered an issue in my Angular project where my unit tests are failing with the following error message: TypeError: Cannot read properties of undefined (reading 'reRenderOnLangChange') at shouldListenToLangChanges (node_modules/@ngneat/tr ...

Angular micro front-end powered by module federation

I am interested in developing micro front-end applications using module federation. I have successfully implemented it following the guidelines provided on this informative page. However, I am facing a challenge where I want each project to have its own u ...

Utilizing Typescript's baseUrl compiler configuration for node development

Is there a way for node's module loader to support TS's baseUrl compiler option? With the introduction of the baseUrl compiler option in TS 2, project relative require() and import requests are now possible. However, this feature requires that ...

No invocation of 'invokeMiddleware' was suggested

Encountered this specific issue when setting up loopback4 authentication. constructor ( // ---- INSERT THIS LINE ------ @inject(AuthenticationBindings.AUTH_ACTION) protected authenticateRequest: AuthenticateFn, ) { super(authen ...

Form submission returns JSON data with an undefined value from the server

I've been following a tutorial here but ran into some issues due to using newer versions of Angular and Ionic. This is an excerpt from my code: createReview(review){ let headers = new HttpHeaders(); headers.append('Content-Type&apo ...

Ways to use DecimalPipe for rounding numbers in Angular - Up or down, your choice!

Looking to round a number up or down using DecimalPipe in Angular? By default, DecimalPipe rounds a number like this: Rounding({{value | number:'1.0-2'}}) 1.234 => 1.23 1.235 => 1.24 But what if you want to specifically round up or do ...

What are the steps for integrating angular2 starter with express?

Can someone explain how to integrate the following Angular starter template into an Express framework? https://github.com/gdi2290/angular-starter I am able to start the webpack dev server without any issues, but I would like to utilize additional librari ...

Tips for showcasing all values in a nested array

In my Vue application, I am dealing with a nested array where users can select one date and multiple times which are saved as one object. The challenge I am facing now is how to display the selected date as a header (which works fine) and then list all the ...

Angular 14: Removing elements from FormArray causes the remaining elements to lose their values

My form includes custom inputs and utilizes the ControlValueAccessor. To view the implementation, visit this link. I encountered an issue where deleting an item from a FormArray would inadvertently clear the values of the other FormGroups still present in ...

TypeScript in Angular causing lodash tree shaking failure

I am currently working on a large project that involves TypeScript. Various attempts have been made to optimize the use of lodash in my project. Before making any conclusions, I believe it is important to review the outcomes of my efforts. The command I ...

What strategies can I employ to prevent redundancy when all my .vue files are identical?

Although I am new to Vue, there are many aspects that I find appealing. However, one thing I dislike is combining templates, scripts, and styles in the same file. Instead, I prefer separating these concerns by using: <template src="./template.html"> ...

Incorporating a Custom CKEditor5 Build into an Angular Application

I am currently in the process of developing an article editor, utilizing the Angular Integration for CKEditor5. By following the provided documentation, I have successfully implemented the ClassicEditor build with the ckeditor component. Below are the ess ...