You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
app.ts and node_modules are in the same directory. When I run ts-node app.ts, reports following error:
SyntaxError: Unexpected token export
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:387:25)
at Module._extensions..js (module.js:422:10)
at Object.require.extensions.(anonymous function) as .ts
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Module.require (module.js:367:17)
at require (internal/module.js:20:19)
at Object. (/Users/kevin.zeng/Projects/ringcentral-js-client/codegen/ts-sample/app.ts:1:1)
at Module._compile (module.js:413:34)
The code runs normally when compiled to js using tsc. Version info:
Since I'm using Typescript for my project, I also prefer Typescript modules as the dependencies. So I think it's necessary to compile dependencies or project won't work using ts-node.
Reacted by Huan Li, Aditya Gangipamula, Aymeric Beaumet, jdmichaud, Richard Wossal, Andrei Senaev, Joe Pea, Reinis Ivanovs, Benno M, Alexander Murmann and 22 more
Reacted by Cameron Tacklind
Reacted by Joe Pea, Ionel lupu, Mickael Bourgois and Yaron
Realistically, the setup you're building is kind of awkward. You're relying on a global mutation that'll be done by a dependent. Why not just compile the files to JavaScript? What about having both projects register with ts-node? What if one project uses different compilation settings to the other? Or they have different dependencies on .d.ts files that happen to conflict when you put them together?
Reacted by Jan Molak, Kai Röder, Kimmo Kiiski, Dmitry Karpunin, Cameron Tacklind and Viktor Shchelochkov
@blakeembrey thanks for point me from #158 to here, sorry for not notice this issue before I post.
I do suggest ts-node to compiling dependencies. because is a good way to modulize pure typescript code if we do not want to compile .ts file any more. (it's why ts-node here, right?)
@zengfenfei I ran into the same issue as you today. I have to make this work by soft link this:
$ mv node_modules/my_mod .
$ ln ../my_mod node_modules
# then ts-node will compile it...
By the way, there's a similar issue here: #135. I think the correct solution, as mentioned in that issue, is to implement --ignore and --include flags which default to ignore: ['node_modules/**'].
@cleavera No, they don't. You should probably do some research into the topic yourself to get familiar. TypeScript libraries should be distributed in JavaScript with declarations enabled. Please don't publish raw TypeScript libraries and fragment the ecosystem for no reason. Internally, you can do whatever you want of course.
Reacted by Mark Pieszak, Lucas Theisen, Abraham White, Patrick Kunka, Vincent Engel and Arthur
I had a similar problem to what @zixia had (sharing internal code between Typescript projects) which led me to this issue. Since it appears to be a design decision not to support .ts files in the node_modules folder, the solution I went with was to use a postinstall script in the library's package.json.
Example:
"scripts": {
"postinstall": "tsc -d -p ."
},
I also added a tsconfig.json file to the root folder of the library with all the compiler settings.
Reacted by Aymeric Beaumet, Michał Pokrywka and Rob Crawford
The hard coded node_modules is actually a problem for repositories relying on how require works to load sub-projects in the same monorepo (like Pouchdb, Cerebraljs). If you store your projects like this:
node_modules // <--- root node_modules for installed deps
packages
+ node_modules
+ @myorg
+ moduleA // <--- now this one can import latest '@myorg/moduleB' without linking and such
+ moduleB
This setup works fine until testing cannot happen because ts-node does not compile in node_modules (which is in the test path).
Please give us a way to fix this.
Reacted by Philipp Katz, Pierrick Bignet, Ryan Ruan, Jerome S., Gerhard Seidel, Kyle Pittman, Stephan Bijzitter, Jarrod Davis and Viktor Shchelochkov
@blakeembrey Can you please explain in what sense using a public API is bad practice ?
Using node_modules to load modules is totally part of node.js API. There is no hack whatsoever here. Reasons to use such a folder architecture are absolutely valid. Here is a discussion related to PouchDB: alle monorepo, we don't have a public summary of our discussion at Cerebral.js but the reasons are similar and I have also good reasons with Lucidity to move away from lerna.
I think there are simple ways to avoid compiling vendor modules and still allow complex open source projects to use ts-node for testing. One such way would be to be able to specify, like .gitignore does for example:
@gaspard Yes, it's valid. Believe it or not, I know how the node.js module system works. I would never promote someone publishing TypeScript first class, you should be publishing JavaScript. If you've done development with node.js for a while, you'll probably remember how CoffeeScript turned out - you have a bunch of people writing .coffee files and just adding coffee-script/register so they could avoid transpiling - even after publishing to npm. I don't intend to ever support that, but it really is a two second change to support it via CLI or environment flags. You could probably have done that quicker than you posted your response.
As my perspective, I agree with @gaspard before, but I have to say, today I'll agree with @blakeembrey.
Last year, I want to publish pure TypeScript module to NPM, and actually, I did. I also have a workaround about this, you could have a look at this thread at #155 (comment) .
The reason I want to do this is that at first:
I fall in love with TypeScript so I want to use it anywhere(ts only)
I'm not familiar with public TypeDefination file with my module
I'm not familiar with ES6 Module with Rollup tools
Today, I learned from Angular how to publish NPM in UMD format with TypeDefination, it's very easy to do this with an npm script, just as @blakeembrey said, really is a two seconds work. So I have no reason to keep my module in ts only.
At last, if there's no dark side of using pure TypeScript NPM module, I believe it is possible to support it by ts-node. However, the dark side I could image is: when a javascript developer found your module from NPM and npm -i it, but it could not be able to run.. This will do hurt the npm eco-system.
So today I vote NO for publishing pure TypeScript module to NPM. Hope this could help others like me to make the right decision today. :)
In case it helps anyone, here's how to do it using the API (instead of CLI) with regex(es):
require('ts-node').register({typeCheck: false,transpileOnly: true,files: true,// HERE, you can use RegExp literals here.ignore: [/node_modules\/(?!@scoped\/package)/,/node_modules\/(?!unscoped-package)/],compilerOptions: require('./tsconfig.json').compilerOptions,})
Reacted by Vít Rozsíval, int0h, Yue Liu, raphael22, Kirill Nikolaev, Uladzimir Kasacheuski and paul-b
Node.js v13 adds new complications. For anyone stumbling here, this is what you may face if you're using Node.js v13+, but I have not found a solution yet.
It seems the ignore trick no longer works if both using module: 'commonjs' and having dependencies that are published as ES Modules.
So although my ignore options is set correctly like I had it before Node 13 while I have module set to commonjs, I get an error like the following error when Node tries to import an ES Module from the CommonJS module output of ts-node:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/trusktr/src/infamous+infamous/node_modules/lowclass/index.js
require() of ES modules is not supported.
require() of /Users/trusktr/src/infamous+infamous/node_modules/lowclass/index.js from /Users/trusktr/src/infamous+infamous/src/core/Observable.ts is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /Users/trusktr/src/infamous+infamous/node_modules/lowclass/package.json.
Now you may think "just change module to esnext". Well, it ain't that easy!
Here's the problem: the entry point that loads ts-node is still a CommonJS module, so as soon as ts-node supplies ES Module output, then you'll get an error when you import your first .ts file, like:
import * as fs from 'fs';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:1055:16)
at Module._compile (internal/modules/cjs/loader.js:1103:27)
at Module.m._compile (/Users/trusktr/src/infamous+infamous/node_modules/ts-node/src/index.ts:536:23)
at Module._extensions..js (internal/modules/cjs/loader.js:1159:10)
at Object.require.extensions.<computed> [as .ts] (/Users/trusktr/src/infamous+infamous/node_modules/ts-node/src/index.ts:539:12)
at Module.load (internal/modules/cjs/loader.js:988:32)
at Function.Module._load (internal/modules/cjs/loader.js:896:14)
at Module.require (internal/modules/cjs/loader.js:1028:19)
at require (internal/modules/cjs/helpers.js:72:18)
Next, you might think "well, now just convert the .js file that loads ts-node into an ES Module instead of CommonJS and give it the .mjs extension or use --input-type=module, and now import your .ts file instead of requireing it". For example:
importtsNodefrom'ts-node'tsNode.register({typeCheck: false,transpileOnly: true,files: true,project: './tsconfig.json',ignore: false,compilerOptions: {baseUrl: './',module: 'esnext',// out with the old, in with the new!},})// require('./readem.ts') // instead of this,import'./readem.ts'// now try this.
Unfortunately, now this won't work, because .ts extensions are not something that ES Modules understand by default, so now errors like the following happen:
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /Users/trusktr/src/infamous+infamous/readem.ts imported from /Users/trusktr/src/infamous+infamous/readem.mjs
TLDR: ts-node is not yet in good shape to deal with the new ES Modules (unless I missed something).
Reacted by Chris Bailey, mtone, Dan Dascalescu, Erik Hughes, Eric Hiller, AnonymousCoder2020, Oleg Kuzmenko, Jan R. Biasi, Mickael Bourgois, Jordan Last and 4 more
Node.js v13 adds new complications. For anyone stumbling here, this is what you may face if you're using Node.js v13+, but I have not found a solution yet.
It seems the ignore trick no longer works if both using module: 'commonjs' and having dependencies that are published as ES Modules.
So although my ignore options is set correctly like I had it before Node 13 while I have module set to commonjs, I get an error like the following error when Node tries to import an ES Module from the CommonJS module output of ts-node:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/trusktr/src/infamous+infamous/node_modules/lowclass/index.js
require() of ES modules is not supported.
require() of /Users/trusktr/src/infamous+infamous/node_modules/lowclass/index.js from /Users/trusktr/src/infamous+infamous/src/core/Observable.ts is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /Users/trusktr/src/infamous+infamous/node_modules/lowclass/package.json.
Now you may think "just change module to esnext". Well, it ain't that easy!
Here's the problem: the entry point that loads ts-node is still a CommonJS module, so as soon as ts-node supplies ES Module output, then you'll get an error when you import your first .ts file, like:
import * as fs from 'fs';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:1055:16)
at Module._compile (internal/modules/cjs/loader.js:1103:27)
at Module.m._compile (/Users/trusktr/src/infamous+infamous/node_modules/ts-node/src/index.ts:536:23)
at Module._extensions..js (internal/modules/cjs/loader.js:1159:10)
at Object.require.extensions.<computed> [as .ts] (/Users/trusktr/src/infamous+infamous/node_modules/ts-node/src/index.ts:539:12)
at Module.load (internal/modules/cjs/loader.js:988:32)
at Function.Module._load (internal/modules/cjs/loader.js:896:14)
at Module.require (internal/modules/cjs/loader.js:1028:19)
at require (internal/modules/cjs/helpers.js:72:18)
Next, you might think "well, now just convert the .js file that loads ts-node into an ES Module instead of CommonJS and give it the .mjs extension or use --input-type=module, and now import your .ts file instead of requireing it". For example:
importtsNodefrom'ts-node'tsNode.register({typeCheck: false,transpileOnly: true,files: true,project: './tsconfig.json',ignore: false,compilerOptions: {baseUrl: './',module: 'esnext',// out with the old, in with the new!},})// require('./readem.ts') // instead of this,import'./readem.ts'// now try this.
Unfortunately, now this won't work, because .ts extensions are not something that ES Modules understand by default, so now errors like the following happen:
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /Users/trusktr/src/infamous+infamous/readem.ts imported from /Users/trusktr/src/infamous+infamous/readem.mjs
TLDR: ts-node is not yet in good shape to deal with the new ES Modules (unless I missed something).
Same situation
Reacted by Dan Dascalescu, Erik Hughes, Cal Freitas, Will Stott, Michał Katański, roger-marley-lrn, Dawson Botsford, Benjamin G, Viktor Shchelochkov and Denis L.
@Bnaya, the initial question did not relate to an ESM module (see #1007 for that), but to the direct import of a TypeScript file from a node_module. @romainPrignon's suggestion to change the default ignore pattern from node_modules to node_modules/(?!module1|module2|...) does the trick.
@cspotcode, would it be worth adding this to the documentation? I'd think it's quite a common scenario to want skip the compilation of one's own node module and import the TypeScript files directly.
Thank @blakeembrey for the explanation. I'll leave one more TL;DR here.
In most cases it really makes sense to only publish compiled Javascript files along with Typescript type definitions. Their compilation/generation should be properly handled by the project itself and not its dependents. From the opposite side, the dependent projects should just use ready Javascript files and know nothing about their generation.
If it's really needed, Typescript files inside node_modules folder still can be executed. For this one needs to use ts-node with --ignore="another-ignore-pattern" option that overrides the default ignore pattern (which is node_modules).
To accept all files you can pass a pattern that doesn't match any string, e. g. --ignore="(?!.*)".
It is also possible to run tools which use ts-node internally for parsing Typescript files that import code from node_modules. For example, it can be Webpack with Typescript configuration file. In order to do so, install cross-env and prepend cross-env TS_NODE_IGNORE="(?!.*)" to npm script command.
I believe I've hit this issue with a project using Node.js v14. Basically, I'm trying to use a dependency with ES Modules and "type": "module" in its package.json, and getting the error below:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: $PROJECTS/three.js/examples/jsm/deprecated/Geometry.js
require() of ES modules is not supported.
require() of $PROJECTS/three.js/examples/jsm/deprecated/Geometry.js from $PROJECTS/three-to-cannon/test/index.test.ts is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename Geometry.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from $PROJECTS/three.js/examples/jsm/package.json.
It seems to be the same issue described here (or have I got that wrong?) so I'm a bit surprised to see it marked as a "won't fix". Are ES Modules simply not supported, and there's no interest in supporting them? Support for ES Modules in Node.js itself has been improving in recent versions, and I'd be glad to see ts-node take advantage of that. :)
I'm also running into similar issues. I have a dependency that distributes itself compiled to ES2015 I believe, with ES modules. I'm having a difficult time messing with all of the possible Node.js and ts-node settings to try and get it to work. Fortunately for me, I control the dependency so I might just go add a commonjs compilation to it.
Until this point, ts-node has generally worked wonderfully for me. The dream for me would be for ts-node to simply handle any files or dependencies that you point at it, be they JavaScript, TypeScript, CommonJS, or ES Modules. IMO ts-node should simply take an initial file as input and just make it work
Activity
[-]Fail to load modules from node_moules[/-][+]Fail to load module from node_moules[/+]blakeembrey commentedon Jul 22, 2016
ts-nodeis not compiling dependencies. Do you feel like it should be?zengfenfei commentedon Jul 25, 2016
Since I'm using Typescript for my project, I also prefer Typescript modules as the dependencies. So I think it's necessary to compile dependencies or project won't work using
ts-node.blakeembrey commentedon Jul 26, 2016
Realistically, the setup you're building is kind of awkward. You're relying on a global mutation that'll be done by a dependent. Why not just compile the files to JavaScript? What about having both projects register with
ts-node? What if one project uses different compilation settings to the other? Or they have different dependencies on.d.tsfiles that happen to conflict when you put them together?huan commentedon Jul 26, 2016
@blakeembrey thanks for point me from #158 to here, sorry for not notice this issue before I post.
I do suggest ts-node to compiling dependencies. because is a good way to modulize pure typescript code if we do not want to compile .ts file any more. (it's why ts-node here, right?)
@zengfenfei I ran into the same issue as you today. I have to make this work by soft link this:
more detail you can find in my dup issue #158
blakeembrey commentedon Jul 30, 2016
By the way, there's a similar issue here: #135. I think the correct solution, as mentioned in that issue, is to implement
--ignoreand--includeflags which default toignore: ['node_modules/**'].blakeembrey commentedon Aug 4, 2016
@cleavera No, they don't. You should probably do some research into the topic yourself to get familiar. TypeScript libraries should be distributed in JavaScript with declarations enabled. Please don't publish raw TypeScript libraries and fragment the ecosystem for no reason. Internally, you can do whatever you want of course.
rjnienaber commentedon Feb 16, 2017
I had a similar problem to what @zixia had (sharing internal code between Typescript projects) which led me to this issue. Since it appears to be a design decision not to support .ts files in the
node_modulesfolder, the solution I went with was to use a postinstall script in the library's package.json.Example:
I also added a tsconfig.json file to the root folder of the library with all the compiler settings.
gaspard commentedon May 28, 2017
The hard coded
node_modulesis actually a problem for repositories relying on how require works to load sub-projects in the same monorepo (like Pouchdb, Cerebraljs). If you store your projects like this:This setup works fine until testing cannot happen because ts-node does not compile in
node_modules(which is in the test path).Please give us a way to fix this.
blakeembrey commentedon May 28, 2017
@gaspard You can start with the README. I have no intention of supporting bad practice by default.
gaspard commentedon Jun 5, 2017
@blakeembrey Can you please explain in what sense using a public API is
bad practice?Using
node_modulesto load modules is totally part of node.js API. There is no hack whatsoever here. Reasons to use such a folder architecture are absolutely valid. Here is a discussion related to PouchDB: alle monorepo, we don't have a public summary of our discussion at Cerebral.js but the reasons are similar and I have also good reasons with Lucidity to move away from lerna.I think there are simple ways to avoid compiling vendor modules and still allow complex open source projects to use
ts-nodefor testing. One such way would be to be able to specify, like.gitignoredoes for example:blakeembrey commentedon Jun 5, 2017
@gaspard Yes, it's valid. Believe it or not, I know how the node.js module system works. I would never promote someone publishing TypeScript first class, you should be publishing JavaScript. If you've done development with node.js for a while, you'll probably remember how CoffeeScript turned out - you have a bunch of people writing
.coffeefiles and just addingcoffee-script/registerso they could avoid transpiling - even after publishing to npm. I don't intend to ever support that, but it really is a two second change to support it via CLI or environment flags. You could probably have done that quicker than you posted your response.huan commentedon Jun 6, 2017
As my perspective, I agree with @gaspard before, but I have to say, today I'll agree with @blakeembrey.
Last year, I want to publish pure TypeScript module to NPM, and actually, I did. I also have a workaround about this, you could have a look at this thread at #155 (comment) .
The reason I want to do this is that at first:
Today, I learned from Angular how to publish NPM in UMD format with TypeDefination, it's very easy to do this with an npm script, just as @blakeembrey said, really is a two seconds work. So I have no reason to keep my module in ts only.
At last, if there's no dark side of using pure TypeScript NPM module, I believe it is possible to support it by ts-node. However, the dark side I could image is: when a javascript developer found your module from NPM and
npm -iit, but it could not be able to run.. This will do hurt the npm eco-system.So today I vote NO for publishing pure TypeScript module to NPM. Hope this could help others like me to make the right decision today. :)
12 remaining items
blakeembrey commentedon Jan 16, 2019
@hanvyj I'm not quite sure I follow or understand why it's an issue with
ts-node, care to elaborate?hanvyj commentedon Jan 16, 2019
It's not! Turns out you can do what I want with the
ignoreconfiguration. Ignore me.trusktr commentedon Jun 5, 2019
In case it helps anyone, here's how to do it using the API (instead of CLI) with regex(es):
trusktr commentedon Jan 2, 2020
Node.js v13 adds new complications. For anyone stumbling here, this is what you may face if you're using Node.js v13+, but I have not found a solution yet.
It seems the
ignoretrick no longer works if both usingmodule: 'commonjs'and having dependencies that are published as ES Modules.So although my
ignoreoptions is set correctly like I had it before Node 13 while I havemoduleset tocommonjs, I get an error like the following error when Node tries to import an ES Module from the CommonJS module output of ts-node:Now you may think "just change
moduletoesnext". Well, it ain't that easy!Here's the problem: the entry point that loads
ts-nodeis still a CommonJS module, so as soon as ts-node supplies ES Module output, then you'll get an error when you import your first.tsfile, like:Next, you might think "well, now just convert the
.jsfile that loadsts-nodeinto an ES Module instead of CommonJS and give it the.mjsextension or use--input-type=module, and nowimportyour.tsfile instead ofrequireing it". For example:Unfortunately, now this won't work, because
.tsextensions are not something that ES Modules understand by default, so now errors like the following happen:TLDR:
ts-nodeis not yet in good shape to deal with the new ES Modules (unless I missed something).xmsz commentedon Jan 12, 2020
Same situation
Bnaya commentedon Mar 17, 2020
I wrote i gist of how it cloud work together (ts + esm)
https://gist.github.com/Bnaya/0d544f4fba966af37da079ee7e8ec08d
Using experimental loaders hooks api. its not a complete impl by no-mean.
Also the api is considered none-stable
Bundle files
renehamburger commentedon Jul 3, 2020
@Bnaya, the initial question did not relate to an ESM module (see #1007 for that), but to the direct import of a TypeScript file from a node_module. @romainPrignon's suggestion to change the default ignore pattern from
node_modulestonode_modules/(?!module1|module2|...)does the trick.@cspotcode, would it be worth adding this to the documentation? I'd think it's quite a common scenario to want skip the compilation of one's own node module and import the TypeScript files directly.
nicky1038 commentedon Nov 3, 2020
Thank @blakeembrey for the explanation. I'll leave one more TL;DR here.
In most cases it really makes sense to only publish compiled Javascript files along with Typescript type definitions. Their compilation/generation should be properly handled by the project itself and not its dependents. From the opposite side, the dependent projects should just use ready Javascript files and know nothing about their generation.
If it's really needed, Typescript files inside
node_modulesfolder still can be executed. For this one needs to usets-nodewith--ignore="another-ignore-pattern"option that overrides the default ignore pattern (which isnode_modules).To accept all files you can pass a pattern that doesn't match any string, e. g.
--ignore="(?!.*)".It is also possible to run tools which use ts-node internally for parsing Typescript files that import code from
node_modules. For example, it can be Webpack with Typescript configuration file. In order to do so, installcross-envand prependcross-env TS_NODE_IGNORE="(?!.*)"to npm script command.cspotcode commentedon Nov 12, 2020
ts-node options can also be specified in your tsconfig.json file:
See also, the official tsconfig JSON schema which includes our options: https://json.schemastore.org/tsconfig
I can certainly review a PR that adds or updates the relevant documentation to our README.
benallfree commentedon Jan 27, 2021
To allow monorepo packages to be transpiled, something like this works:
donmccurdy commentedon May 21, 2021
I believe I've hit this issue with a project using Node.js v14. Basically, I'm trying to use a dependency with ES Modules and
"type": "module"in itspackage.json, and getting the error below:It seems to be the same issue described here (or have I got that wrong?) so I'm a bit surprised to see it marked as a "won't fix". Are ES Modules simply not supported, and there's no interest in supporting them? Support for ES Modules in Node.js itself has been improving in recent versions, and I'd be glad to see
ts-nodetake advantage of that. :)lastmjs commentedon Jun 8, 2021
I'm also running into similar issues. I have a dependency that distributes itself compiled to ES2015 I believe, with ES modules. I'm having a difficult time messing with all of the possible Node.js and ts-node settings to try and get it to work. Fortunately for me, I control the dependency so I might just go add a commonjs compilation to it.
Until this point, ts-node has generally worked wonderfully for me. The dream for me would be for ts-node to simply handle any files or dependencies that you point at it, be they JavaScript, TypeScript, CommonJS, or ES Modules. IMO ts-node should simply take an initial file as input and just make it work
fider-apptimia commentedon Jul 29, 2021
Same here... Any solution?
cspotcode commentedon Jul 29, 2021
Use #1007