Lukas Pirkl
Lukas Pirkl

Reputation: 1447

Conditional import to switch implementations

I have node.js application written in TypeScript and I need to switch between two interface implementations based on the config file. Currently I have this code which seems to be working.

"use strict";

import { config } from "../config";

let Something;
if (config.useFakeSomething) {
    Something = require("./FakeSomething").FakeSomething;
} else {
    Something = require("./RealSomething").RealSomething;
}
...
let s = new Something();
s.DoStuff();
...

But I have bad gut feeling about that (mainly because of the mixing require and import for loading modules). Is there some other way how to achieve implementation switching based on config file without importing both modules?

Upvotes: 19

Views: 25388

Answers (5)

MetaZebre
MetaZebre

Reputation: 919

A modern answer using the import() function:

import { config } from "../config";

let Something;
if (config.useFakeSomething) {
    Something = (await import("./FakeSomething")).FakeSomething;
} else {
    Something = (await import("./RealSomething")).RealSomething;
}
...
let s = new Something();
s.DoStuff();
...

Remember that import() is non blocking, so you need to add await if the code that follows needs the result from the import().

Upvotes: 8

o.z
o.z

Reputation: 1156

In addition to the correct answers above, in case you need this switching for many files within a single folder, you can use a symbolic-link (not available on Windows) that referenced to the right folder, so your code remains clean.

This approach is good for switching between real code and stubs, for instance

Upvotes: 0

You can do it like that:

let moduleLoader:any;

if( pladform == 1 ) {
    moduleLoader = require('./module1');
} else {
    moduleLoader = require('./module2');
}

and then

if( pladform === 1 ) {
    platformBrowserDynamic().bootstrapModule(moduleLoader.module1, [ languageService ]);
}
else if ( pladform === 2 ) {
    platformBrowserDynamic().bootstrapModule(moduleLoader.module2, [ languageService ]);
}

Upvotes: 1

Calvin Belden
Calvin Belden

Reputation: 3104

If you want to keep the client-code for your Something class clean, you can move the conditional importing to a single file. You can have the following directory structure for your Something module:

/Something
    RealSomething.ts
    FakeSomething.ts
    index.ts

And in your index.ts, you can have the following:

import { config } from '../config';

const Something = config.useFakeSomething ?
    require('./FakeSomething').FakeSomething :
    require('./RealSomething').RealSomething;

export default Something;

And in your client code, you can just import Something:

import Something from './Something/index';

Upvotes: 8

Amid
Amid

Reputation: 22352

I can see nothing wrong with your approach. In fact lines like

import { config } from "../config";

When targeting commonjs will be compiled to the following javascript (ES6):

const config = require('../config');

So they are effectively identical and you are not mixing different module loading techniques.

Upvotes: 6

Related Questions