At Prosopo, we're using TypeScript to build Procaptcha, as it offers static type checking and improved code quality. However, running TypeScript requires a transpiler to convert TypeScript code to JavaScript. One of the most popular tools for this task is ts-node
, which compiles TypeScript files on-the-fly and executes them directly in Node.js. This is very useful, but there are a couple of problems with ts-node
that we will explore in this article.
ts-node
ts-node
compiles TypeScript files on-the-fly, which can introduce a significant performance overhead compared to precompiled JavaScript files. Each time a TypeScript file is executed, ts-node
must transpile the code to JavaScript before running it in Node.js. This compilation step can slow down the startup time of your application, especially for larger codebases.
This is a strange one. You would imagine that ts-node
would be able to run TypeScript files out of the box. However, a simple script that logs something to the console will fail. Our script.ts
contains the following code:
console.log('In a TS File!')
When you try to execute this script from the command line, you get the following rather perplexing error:
> node --version
v20.12.2
> ts-node --version
v10.9.2
> ts-node script.ts
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /home/user/dev/script.ts
OK, let's try the --esm
flag:
> ts-node --esm script.ts
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /home/user/dev/script.ts
OK, let's try switching the node version:
> nvm use 18
Now using node v18.18.2 (npm v10.5.2)
> ts-node script.ts
zsh: command not found: ts-node
> npm i -g [email protected]
added 20 packages in 3s
> ts-node --version
v10.9.2
> ts-node script.ts
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"
OK, time to try something else, it's sunny outside and we're getting nowhere. ☀️
ts-node
🌅️Slow load times and unexpected errors are a couple of the problems we face when using ts-node
. Here are some alternative approaches.
tsc
One of the most straightforward alternatives to ts-node
is precompiling TypeScript files with the TypeScript compiler (tsc
). By running tsc
to compile TypeScript files to JavaScript before executing them in Node.js, you benefit from static type checking, improved performance, and better debugging support. It takes slightly longer to test your code but its a more robust solution.
In the above example we would run the following commands:
> tsc script.ts
> node script.js
In a TS File!
However, its worth noting that more complex setups will require a tsconfig.json
file to configure TypeScript.
tsx
compiles TypeScript files on-the-fly, similar to ts-node
, but with a much faster startup time because its using esbuild under the hood. Esbuild is written in Go, whereas most JavaScript build tools are written in JavaScript. Javascript is an interpreted language, which means it will never match a compiled language like Go in terms of computation and raw performance. Go was made by Google and designed for high performance.
> tsx --version
tsx v4.15.7
node v18.18.2
> tsx script.ts
In a TS File!
Our tiny file instantly runs, with no load time, and no tsconfig.json required. Hooray!
tsx
Fast load times and easy CLIs are great but there are some limitations to be aware of.
From the tsx
site:
TypeScript & ESM transformations are handled by esbuild, so it shares some of the same limitations such as: Compatibility with eval() is not preserved Only certain tsconfig.json properties are supported emitDecoratorMetadata is not supported For details, see esbuild's JavaScript caveats and TypeScript caveats documentation.
ts-node
is an enduringly popular tool for running TypeScript on-the-fly. However, it has some serious limitations in terms of user experience. If you want to run a simple script, and not wait ages for it to load, tsx
is a great replacement. However, when it comes to build time, stick to tsc
to ensure that your types are checked and your code is safe. All in all, with the alternatives that exist today, we think it's time to drop ts-node!
No ts-nodes were harmed in the making of this article. 😇