Dynamic TypeScript imports without using Promises
Asked Answered
I

4

7

I have this situation. The reason they are dynamic is to prevent loading 10x the amount of code that I need to load to do a certain command-line task.

if (diagnostics) {
  require('./lib/cli-commands/run-diagnostics').run(sumanOpts);
}
else if (script) {
  require('./lib/cli-commands/run-scripts').run(sumanConfig, sumanOpts);
}
else if (tscMultiWatch) {
  require('./lib/cli-commands/run-tscmultiwatch').run(sumanOpts);
}
else if (repair) {
  require('./lib/cli-commands/run-repair').run(sumanOpts);
}
else if (postinstall) {
  require('./lib/cli-commands/postinstall').run(sumanOpts);
}
else{
  // etc etc
}

if I try a dynamic loading import call, I get this:

enter image description here

It's clearly going to return a Promise not the module.exports value.

Is there a way to use dynamic import syntax without asynchronous loading or no?

Imparipinnate answered 1/12, 2017 at 4:22 Comment(3)
Basically I am looking for "synchronous dynamic imports" instead of "asynchronous dynamic imports"Imparipinnate
Have you observed that there actually is a performance hit from just including all of them?Beery
@Beery there will be a hit, however small, it will load a lot of files, and potentially log things that I don't want to be logged, etc.Imparipinnate
A
4

Just to add to Unional's correct answer, it is very easy to work with the Promise returning dynamic import syntax.

(async function () {
  if (diagnostics) {
    const run = await import('./lib/cli-commands/run-diagnostics');
    run(sumanOpts);
  }
  else if (script) {
    const run = await import('./lib/cli-commands/run-scripts');
    run(sumanConfig, sumanOpts);
  }
}());

Note that if you are using --module commonjs modules then it is likely best to stick to require. However, the above is perfect for --module amd, --module system, and of course --module esnext.

Angelenaangeleno answered 1/12, 2017 at 7:25 Comment(4)
yeah I frankly don't see why supporting a dynamic synchronous import would not be possible, but I guess it's a restriction of ES that TS has to adhere toImparipinnate
Yes but it is a good restriction, I don't see a need for dynamic synchronous import. I would rather see a top level await construct. But again, runtimes can add extra features, like Node adds require, so there isn't a problem.Angelenaangeleno
it is not working for me.. #60056719Sufferable
@kumaresan_sd If you read the question asked here, you will see that it is different from the question you asked in your post. I read your post, and you have a different and unrelated issue. I would be happy to help you with that, but it's rather unhelpful to downvote an answer to a largely unrelated question that was accepted as working to get help with your own especially since you didn't read the question here carefully. Your problem is that you're loading from the wrong path and getting a 404. That's a different problem.Angelenaangeleno
C
3

By the nature of dynamic import, it is asynchronous.

require() is synchronous because it lives on the server side. You can read a file synchronously using (for example) fs.readFileSync().

For the new dynamic import, it is designed to work on the client side so there will be an ajax request back to the server to perform the import.

Thus it has to be asynchronous.

Cougar answered 1/12, 2017 at 5:44 Comment(2)
seems like it, if I get no further info, will have to accept this answerImparipinnate
Why do you don't want it to be asynchronous? Are you not happy with the Promise syntax or....?Cougar
T
2

I recently wrote import-sync which may help with this use case.

The library is a wrapper around esm and enables ESM imports from both ES6 and CJS-based NodeJS projects.

I haven't experimented extensively with TS dynamic imports, but from what I've tried/tested, it does run with ts-node.

For example,

// const importSync = require('import-sync');
import importSync from 'import-sync';

if (diagnostics) {
  importSync('./lib/cli-commands/run-diagnostics').run(sumanOpts);
}
else if (script) {
  importSync('./lib/cli-commands/run-scripts').run(sumanConfig, sumanOpts);
}
else if (tscMultiWatch) {
  importSync('./lib/cli-commands/run-tscmultiwatch').run(sumanOpts);
}
else if (repair) {
  importSync('./lib/cli-commands/run-repair').run(sumanOpts);
}
else if (postinstall) {
  importSync('./lib/cli-commands/postinstall').run(sumanOpts);
}
else{
  // etc etc
}
Thousand answered 17/10, 2023 at 10:53 Comment(0)
H
1
  1. Asynchronous-only dynamic import() is an ECMAScript feature, and the trend in TypeScript evolution is to stick to ECMAScript where possible.

  2. TypeScript can be configured to output JS in different ways and accommodate different module systems. It’s true that one of those options is to transpile your TS project all into a single JS file that uses AMD, in which case TypeScript converts all of your imports into synchronous require()s, meaning you could have a synchronous import() function. However, that’s only one of all possible transpilation targets. You can see that it’s understandable if TypeScript doesn’t want to introduce a new way of import()—incompatible with ECMAScript!—as a special case for just one possible transpilation mode.

Haywire answered 28/5, 2023 at 0:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.