TypeScript ES dynamic `import()`
This is a bug in the Typescript Compiler which will be fixed in 2.5.
Exporting a default object with a function that imports a file will not compile the import
statement into a require
statement in Typescript 2.4.x.
For example, while this:
export const sudo = { run() { return import('./test3'); } }
Will compile to this:
exports.sudo = { run: function () { return Promise.resolve().then(function () { return require('./test3'); }); } };
This:
export default { run() { return import('./test3'); } }
Compiles into this:
exports.default = { run: function () { return import('./test3'); } };
Which is obviously wrong. A temporary solution would be this:
export const sudo = { run() { return import('./test3'); } }
export default sudo;
Which compiles (correctly) into this:
exports.sudo = { run: function () { return Promise.resolve().then(function () { return require('./test3'); }); } };
exports.default = exports.sudo;
Related videos on Youtube
Roomy
Updated on June 04, 2022Comments
-
Roomy almost 2 years
While using the new TypeScript feature, so called ES Dynamic Imports, I am not able to run the code of my isomorphic app on the server side using
ts-node
.It seems like the error does not occur when using the webpack module loader which transpiles the code in it's own way and running resulting files in a browser.
The error which I've got:
case 0: return [4 /*yield*/, import("./component/main")]; ^^^^^^ SyntaxError: Unexpected token import
Usually TypeScript transpiles the
import
expression to something like that:Promise.resolve(require("./component/main"))
, but I can't see it there.How to fix that? Does it have something common with
ts-node
? Or there is a "polyfill" fornode.js
?My
tsconfig.json
file:{ "compilerOptions": { "declaration": false, "emitDecoratorMetadata": true, "allowJs": false, "experimentalDecorators": true, "importHelpers": true, "inlineSourceMap": false, "inlineSources": false, "lib": [ "DOM", "ES5", "ES6", "ES7" ], "listFiles": false, "module": "commonjs", "noEmitOnError": true, "noImplicitAny": true, "noImplicitReturns": true, "noImplicitThis": true, "preserveConstEnums": false, "pretty": false, "removeComments": false, "strict": true, "target": "es5" } }
the code:
import * as m from "mithril"; import LayoutComponent from "./component/layout"; const render = ( layout: m.ComponentTypes<any, any>, ) => ({ tag, attrs }: m.Vnode<any, any>) => m(layout, attrs, m(tag as any, attrs)); export default { "/:path...": { onmatch: async (args, path) => (await import("./component/main")).default, render: render(LayoutComponent), }, } as m.RouteDefs;
-
Roomy almost 7 yearsit didn't worked, sorry
-
Roomy almost 7 years> tsc "--version" Version 2.4.2, > ts-node "--version" ts-node v3.3.0 node v8.2.1 typescript v2.4.2
-
Aluan Haddad almost 7 years
"lib": ["dom", "esnext"]
would be better. Not saying it's the issue but I advise changing it. -
Michael FedoraI replicated the error, working on solution now...
-
Michael FedoraAre you using local (node_modules) tsc/ts-node or global? Are those local/global versions? If you're running linux, does sudo have different version than your local user? etc. That's the only other things I can think of.
-
Aluan HaddadTo get this to work I had to pass the
--compiler
argument explicitly to ts-node. Make it is using the correct version of typescript. -
Roomy@edit I've pasted the code which is used
-
Roomy@edit - updated by
tsconfig.json
-
Michael Fedora
tsc --version
gives you what?
-
-
Roomy almost 7 yearsOkay, so in other words I'm forced to use Promise instead of async/await?
import(...).then((cmp) => cmp.default)
should do the trick, am I correct? -
Michael Fedora almost 7 yearsNo; you are forced to export a non-default object, and then export default that object. Async/await will still work (afaik, I can keep trying)
-
Roomy almost 7 yearsyep, you are right, I can not use that syntax, thanks for explaining that
-
Michael Fedora almost 7 yearsYou can still keep the rest of your code the same (using the "default" object, etc), just make sure you are also exporting a sudo-default first, and then exporting said sudo-default as the "default" so that it compiles correctly.
-
Frank Nocke over 6 yearsI am on Typescript 2.5.3 (judged from
package.version
andyarn list
) and the bug is still present. -
Michael Fedora over 6 yearsSeems to be fixed in 2.6.
-
chharvey about 5 yearsoff-topic question, but what’s the difference between
Promise.resolve().then(() => require('./test3'))
andPromise.resolve(require('./test3'))
? -
Michael Fedora about 5 yearsthe first will run the lambda function when the promise is resolved, the second will run the require function before it is resolved, because you are not passing a function there but rather the result of the
require()
call.