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.