22

I'm trying to run a script created in a regular folder with two .ts files. One with the script and one with helper functions to run it. I'm also importing more things such as axios or form-data.

The thing is that when I try to run the script with ts-node: node script.ts, the following error appears:

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"

My package.json:

{
  "dependencies": {
    "@types/node": "^17.0.23",
    "axios": "^0.26.1",
    "form-data": "^4.0.0",
    "showdown": "^2.0.3",
    "ts-node": "^10.7.0",
    "typescript": "^4.6.3"
  },
  "type": "module"
}

And my tsconfig.json:

{
  "compilerOptions": {
    "esModuleInterop": true
  },
  "include": ["/**/*.ts"],
  "exclude": ["node_modules"]
}

My imports in the script.ts file are:

import { datoManagementPrimaryEnvironment } from "./content.management";
import {
  createContent,
  uploadToCloudfare,
  getEntryFromDatoWithTheId,
  getFilters,
} from "./helpers";

and in helpers.ts:

import { datoManagementPrimaryEnvironment } from "./content.management";
import axios from "axios";
import FormData from "form-data";
var showdown = require("showdown");

Does anyone know what I'm doing wrong? thanks!

TheMaster
  • 45,448
  • 6
  • 62
  • 85
Emiliano
  • 437
  • 1
  • 4
  • 14

5 Answers5

17

Use the --esm switch for ts-node.

Eg

ts-node --esm index.ts

This requires you to have the module to set to one of the newer ones (like nodenext or node16) and moduleResolution also set to a newer method, in your tsconfig.

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
Victor P
  • 1,496
  • 17
  • 29
6

This is what worked for me. Thanks to @Slava for pointing me in the right direction.

Linking the documentation here.

The easiest method is to add esm: true to your TypeScript config file:

{   
  "$schema": "https://json.schemastore.org/tsconfig",  
  "extends": "@tsconfig/node-lts-strictest-esm/tsconfig.json",  
  "compilerOptions": {
    // …   
  },   
  "include": [
    // …   
  ],   
  "ts-node": {
    "esm": true, // «———— enabling ESM for ts-node   
  }, 
} 

The only thing I was missing was adding "esm": true, because I already have ts-config setup for esm. But if you have nothing, it's probably helpful to add the "$schema" and "extends".

I also needed to add "type": "module" in the package.json file.

christo8989
  • 6,442
  • 5
  • 37
  • 43
5

Remove "type": "module" from your package.json

And change your tsconfig.json to:

{
  "compilerOptions": {
    "esModuleInterop": true,
    "moduleResolution": "node"
  },
  "include": ["/**/*.ts"],
  "exclude": ["node_modules"]
}
Thomas H.
  • 170
  • 4
  • 8
    Hi, thanks for the answer, but I already tried that. This error appears then: 'SyntaxError: Cannot use import statement outside a module' – Emiliano Apr 05 '22 at 19:35
  • 1
    `"moduleResolution":"node"` was missing too in `tsconfig.json` – Thomas H. Apr 05 '22 at 19:46
  • 5
    Still appears the same error: 'Unknown file extension ".ts"' – Emiliano Apr 05 '22 at 19:57
  • You changed package.json and tsconfig.json ? hum it's working fine on my computer – Thomas H. Apr 05 '22 at 19:59
  • 3
    When I change those, this previous error appears: SyntaxError: Cannot use import statement outside a module' – Emiliano Apr 05 '22 at 20:04
  • Hi Thomas, I finally solved this. But now when I run the script with 'ts-node script.ts', nothing happens, and I'm logging the errors in the console, but they don't appear... the script should have something? because mine consists in an export default async (req, res) => { ...my script... } – Emiliano Apr 05 '22 at 20:59
  • 2
    Great ! How did you solve it ? Can you share your `script.ts` file pls ? – Thomas H. Apr 06 '22 at 16:04
  • Yeah how did you resolve it, friend? ^ I also have this issue - "Hi, thanks for the answer, but I already tried that. This error appears then: 'SyntaxError: Cannot use import statement outside a module' – " – dylanh724 Oct 30 '22 at 11:44
  • What if I want to use ESM? – Slava Fomin II Nov 15 '22 at 16:40
  • These days it's possible to pass `--esm` to ts-node to make it understand esm, as outlined in @victor-p 's answer. – Sander Mar 04 '23 at 18:04
5

Here's how you use TypeScript with native ESM

  1. Update your package.json to have:
{
  "type": "module",
  // …
}
  1. Install the @tsconfig/node-lts-strictest-esm dependency:
npm i -D @tsconfig/node-lts-strictest-esm
  1. Update your tsconfig.json to have:
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "extends": "@tsconfig/node-lts-strictest-esm/tsconfig.json",
  // …
}
  1. Use imports with .js extension in your TS source files, e.g.:
import { Foo } from './common/foo.js';
  1. Then use the ts-node-esm file.ts command instead of ts-node file.ts.

This should do the trick.


Also, look at the detailed guide.

Slava Fomin II
  • 26,865
  • 29
  • 124
  • 202
-9

When you want to use ts-node you should try running the file with ts-node scripts.ts instead of node scripts.ts.

You can also refer to the usage examples on npmjs.com

lumaghg
  • 1
  • 1