TypeStrong / ts-node

TypeScript execution and REPL for node.js
https://typestrong.org/ts-node
MIT License
12.92k stars 532 forks source link

Suggestion: always run ".ts" files. Don't ever say .ts is unknown. #1967

Open mikemaccana opened 1 year ago

mikemaccana commented 1 year ago

Desired Behavior

There's a whole bunch of closed tickets, online discussion, workarounds, etc. for this:

$ npx ts-node somefile.ts
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"

Regardless of the contents of package.json, the ERR_UNKNOWN_FILE_EXTENSION is not a logical error for a program whose only purpose is to run TypeScript files.

Thanks for understanding the frustration of the many people that have tried to use ts-node to run a .ts file and been told this isn't possible.

Is this request related to a problem?

$ npx ts-node somefile.ts
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"

Additional context

Other tools like esrun have been created precisely because of this issue. Rather than close every ticket with 'user error' it would be better if ts-node ran ts files, just like python runs python files and ruby runs ruby files and bash runs bash files.

mike-lischke commented 1 year ago

I even lean towards saying that when running a ts file ts-node should automatically apply the correct settings (type: module in package.json, module: esnext in tsconfig.ts) if not already properly given.

SeryiBaran commented 1 year ago

Hello!

By default, tsc --init generates config for CJS. CJS code working normal out-of-the-box.

cjs-work

If you need to change between CJS/ESM - try:

For ESM

For CommonJS

mikemaccana commented 1 year ago

Thanks @SeryiBaran but nobody is asking for instructions on how to use ESM. This is a feature request to use sensible defaults automatically to run TS files (including using ESM).

michaelschufi commented 1 year ago

I wholeheartedly agree. Why do I need to set up a tsconfig.json file every time I just want to run a completely normal TypeScript script? This project is way too awesome to have such a learning curve.

By normal, in the year 2023, I mean:

For example: I have a Next.js project that has a database folder which holds migrations. To execute a script to run the migrations, I expect just to do

npx ts-node ./src/backend/db/migrate/index.ts

and it should run.

The hoops you have to jump through if you haven't yet used ts-node:

  1. The import syntax error

    import { migrate } from 'drizzle-orm/planetscale-serverless/migrator';
    ^^^^^^
    
    SyntaxError: Cannot use import statement outside a module
  2. You google and you find that you have to add "type": "module" to your package.json.
  3. Now you get TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"
  4. Alright, let's google that -> You add --esm as an option.
  5. You get CustomError: Cannot find module '/pathtorepo/src/backend/db/db' because you imported the db.ts file like import { db } from '../db';.
  6. You try from '../db.ts' - it doesn't work. TS says you need to use .js.
  7. You can finally run your script. But wait. It fails because of environment variables.
  8. So after another googling session, you realize that importing it is probably not working, and the docs say you need to add -r dotenv/config to the command.
  9. Yay, your script finally runs! 🎉 ... BUT wait - now your eslint config cannot be read any more because you added "type": "module" to your package.json
  10. You remove it, google some more, and you eventually end up having to adjust your tsconfig:
     "ts-node": {
         "moduleTypes": {
             "./src/backend/db": "esm",
         }
     },

This all, to run a simple TypeScript script.

Ah, and you still have the file extension .js in your file import ... from '../db.js';

sangdth commented 1 week ago

Hi @michaelschufi, I would like to ask for your permission to print your awesome comment, so I can put it on the wall? Potentially I will print a t-shirt too.

Thanks.

michaelschufi commented 1 week ago

@sangdth Of course, as long as it's for personal use, no problem :)