Reputation: 6225
What is the TypeScript way of loading modules dynamically (path to the module is known at runtime)? I tried this one:
var x = "someplace"
import a = module(x)
But it seems that TypeScript compiler would like to see path as a string in import/module at compile time:
$ tsc test.ts
/tmp/test.ts(2,19): error TS1003: Identifier expected.
/tmp/test.ts(2,20): error TS1005: ';' expected.
I know I can for example directly use RequireJS (if I use amd module format), but that doesn't feel right to me - it's solution for one particular library.
Upvotes: 53
Views: 107376
Reputation: 8132
I've tried the option without extension, but for me fails in javascript and typescript side going directly to the catch
.
So I've made a workaround including an additional parameter to my function that is 'js' by default.
export const getPackageConfiguration = async (cmdr: Pick<CommanderPackage, 'cmd'>, ext: 'js' | 'ts' = 'js') => {
try {
const config = await import(`./managers/${cmdr.cmd}.${ext}`)
return config?.default
} catch {
return {}
}
}
It work well when I build my files with tsc
command generating js files. And when I run my test (typescript side), I call it with 'ts' to avoid import errors.
await getPackageConfiguration('npm', 'ts')
Upvotes: 1
Reputation: 772
If you want to extract the type from a default export dynamically it can be done like so:
const dynamicImport = await import('path-to-import')
const typedDefaultImport = dynamicImport.default
Upvotes: 7
Reputation: 10298
ES proposal dynamic import is supported since TypeScript 2.4. Document is here.
import
function is asynchronous and returns a Promise
.
var x = 'someplace';
import(x).then((a) => {
// `a` is imported and can be used here
});
Or using async/await
:
async function run(x) {
const a = await import(x);
// `a` is imported and can be used here
}
Upvotes: 92
Reputation: 276229
You need to specify a hard coded string. Variables will not work.
JavaScript now got dynamic imports. So you can do import(x)
:https://developers.google.com/web/updates/2017/11/dynamic-import
TypeScript supports it as well. That said you would still want the argument to be statically analyzable for type safety e.g.
const x = 'someplace';
import(x).then((a) => { // TypeScript knows that `x` is 'someplace' and will infer the type of `a` correctly
});
Upvotes: 20