ts-node: "Unexpected token import" when dependency in .ts is an es6 module

Possibly related issue: https://github.com/TypeStrong/ts-node/issues/505

Setup

ts-node: 7.0.0
typescript: 2.9.2
tape: 4.9.1

Problem: Es6 module dependency doesn’t work

I’m trying to import functions from ramda in my typescript file.

src/index.spec.ts

import add from "ramda/es/add"

node_modules/ramda/es/add.js

import _curry2 from './internal/_curry2';
var add = /*#__PURE__*/_curry2(function add(a, b) {
  return Number(a) + Number(b);
});
export default add;

Then I try to run my test with tape:

ts-node node_modules/tape/bin/tape src/**/*.spec.ts
C:\project\node_modules\ramda\es\add.js:1
(function (exports, require, module, __filename, __dirname) { import _curry2 from './internal/_curry2';
                                                              ^^^^^^
SyntaxError: Unexpected token import
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:616:28)
    at Module._extensions..js (module.js:663:10)
    at Object.require.extensions.(anonymous function) [as .js] (C:\project\node_modules\ts-node\src\index.ts:431:14)
...

CommonJs Dependency works

src/index.spec.ts

import add = require("ramda/src/add")

node_modules/ramda/src/add.js

var _curry2 = /*#__PURE__*/require('./internal/_curry2');
var add = /*#__PURE__*/_curry2(function add(a, b) {
  return Number(a) + Number(b);
});
module.exports = add;

Then I try to run my test with tape:

ts-node node_modules/tape/bin/tape src/**/*.spec.ts
...
# tests 5
# pass  5

# ok

Questions

Is this intended behavior for ts-node? Are there any options I have to use es6 dependencies, or is ts-node not an option in that case?

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 60
  • Comments: 22 (6 by maintainers)

Most upvoted comments

In our case, we’re importing our own code (in our private repo, no transpiling – pure .ts files) on node 10.4.1 using tsconfig excerpt:

"module": "commonjs",
"target": "es2017",

Unless I misread your comment, your explanation wouldn’t seem to apply to us. Copy/pasting the code from our private package into the one attempting to use it resolves the issue, so it appears to have something to do with TypeScript dependencies. Other TypeScript dependencies continue to work fine – it is this one function which we’ve oddly been unable to reference without error.

In my case, flag allowJs: true in tsconfig.json resolved the similar problem 🎉

@blakeembrey Here is the scenario for you understanding. Project A is ES6 based mocha tests(No typescript). Used Babel to transpile to es5 and ran tests. Works fine. Project B is Typescript with ProjectA imported (import {lib} from ProjectA). Tried using node-ts with all combination to tsconfig. Getting unexpected token import issue. From your previous comments, understand that ts-node wont compile node modules, but what is the way/steps to get this working?

will we ever be able to depend on TypeScript dependencies? I’m really tired of compiling into JS. I just want to ts-node .

Having to tsc -w on my linked dependencies in another process isn’t fun

As a possible solution, one can replace ts-node by webpack to chain a typescript parser with babel. Because webpack is so much popular, it will have good tools to process Typescript, even with ES6 Javascript.

Here is a very nice blog explaining how to set up the mocha testing environment to process both typescript and babel. They use the library “mixer” called mocha-webpack. Many people recommend to use mocha with ts-node. This blog gives an alternative. It may be that, with this alternative, the warnings will show up earlier. Besides, webpack and its plugins is very clever to find the node_modules that typescript on its own cannot find unless you cutomize tsconfig.json in a tricky way.

https://engineering.policygenius.com/typescript-mocha-and-babel-ffd07369792a

Edit: the solution above did not work for me. Probably because an old version of webpack is required.

Btw I solved this. The real solution is to compile your npm package code to JS and turn declarations to true on tsconfig. This way you can safely import code in your test files from node_modules plus with declarations you will get TS types too 😀

So @blakeembrey you were right: node_modules should include only valid JS code + d.ts files

The same problem, I think throwing the Error, because you haven’t allowJs or module is not commonjs in tsconfig, I’m the latter.

@hypeofpipe allowJs, not allowJS

TS Node does not compile files in node_modules by default. If you want to consume ES modules, you should update to a node.js version that supports ES modules natively, use something like esm or alter the default behaviour by changing --ignore.

The function in question is:

export function isSingle<T, S extends Model&Instance<T>, M extends Model&Data>(context: S|M): context is S {
	return (<S>context).instance !== undefined;
}

When imported from node_modules (where it is in a .ts file) it gives this error. When copy/pasted into a .ts file not in node_modules (specifically right into the file that wanted to use it) it works fine. Other .ts files in the same subdirectory of node_modules work fine and can be imported from. The only differences I’ve noted are:

  1. In this case I’m importing a function, not a class (more common), and
  2. In this case I’m using the TS type system more… aggressively

Unfortunately, this is all embedded in a significant non-public codebase, and I haven’t had time to boil it down to a minimal repro case yet. It’s on my todo list, but with the copy/paste workaround available it’s not high up, unfortunately.