17

Note: I am aware that the following question is about an experimental feature. I have created a clone on the ts-node discussion forum. However, I believe StackOverflow has a wider exposure and would lead to a solution in less time.

I am trying to make a simple script that reads a file from one location and processes it. Here is what I have so far, having followed #1007:

Node: v12.22.1

my-app
├── .eslintrc.cjs
├── .gitignore
├── in
│   └── given.txt
├── node_modules
├── out
├── package-lock.json
├── package.json
├── src
│   ├── helper.ts
│   └── main.ts
└── tsconfig.json

package.json

{
  "name": "my-app",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "lint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings=0",
    "start": "node --experimental-specifier-resolution=node --experimental-modules --no-warnings --loader ts-node/esm ./src/main.ts"
  },
  "author": "Kaustubh Badrike",
  "devDependencies": {
    "@types/node": "^15.3.0",
    "@typescript-eslint/eslint-plugin": "^4.24.0",
    "@typescript-eslint/parser": "^4.24.0",
    "eslint": "^7.26.0",
    "ts-node": "^9.1.1",
    "typescript": "^4.2.4"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",                                /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "ESNext",                           /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    
    /* Strict Type-Checking Options */
    "strict": true,                                 /* Enable all strict type-checking options. */
    
    /* Module Resolution Options */
    "moduleResolution": "node",                  /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    "esModuleInterop": true,                        /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    
    /* Advanced Options */
    "skipLibCheck": true,                           /* Skip type checking of declaration files. */
    "forceConsistentCasingInFileNames": true        /* Disallow inconsistently-cased references to the same file. */
  }
}

main.ts

import { readFileSync } from "fs";

const contents = readFileSync('../in/given.txt');

However, when I try npm run start, I get the following

TypeError [ERR_INVALID_RETURN_PROPERTY_VALUE]: Expected string to be returned for the "format" from the "loader getFormat" function but got type 
object.
    at Loader.getFormat (internal/modules/esm/loader.js:125:13)
    at Loader.getModuleJob (internal/modules/esm/loader.js:247:20)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:49:17)
    at async Promise.all (index 0)
    at link (internal/modules/esm/module_job.js:53:9)

The error does not occur if I remove the import from fs. Importing items from helper.ts works as well.

What do I need to do to get it to work?

Kaustubh Badrike
  • 495
  • 1
  • 4
  • 18

2 Answers2

10

From this issue comment:

It appears that in Node 16, you can use ts-node-esm when invoking your TypeScript code.

So in summary, in your tsconfig.json file, set

"module": "ESNext",
"moduleResolution": "node"

In package.json set

"type": "module"

Then, when running your script, instead of running ts-node myscript.ts, invoke it via ts-node-esm myscript.ts

double-beep
  • 5,031
  • 17
  • 33
  • 41
mattnedrich
  • 7,577
  • 9
  • 39
  • 45
3

Update 23.05.2021

ts-node v10.0.0 was released and it fixes issues with the resolution of node built-in modules in ESM loader on NodeJS >=12.20.0, <13 which seems to be the issue you are facing.

Original answer

I could reproduce your issue on NodeJS 12.22.1. I can also confirm that it work properly on NodeJS 14.16.

Is updating your NodeJS version a possibility?

Keep in mind that NodeJS support to ESM is experimental for a long time and changes are usually expected in this phase.

Also, related to that fact you are using a version of NodeJS (12.X) that is approaching the end of it's maintenance life, my recommendation is that you update your NodeJS to at least version 14.x either to solve this issue and for you to benefit on the latest development and guarantee long term support.

You can find a more complete answer on the requirements and configurations here: Unable to import ESM .ts module in node

Felipe Plets
  • 7,230
  • 3
  • 36
  • 60