TypeScript has taken the web development world by storm, becoming increasingly popular for enterprise projects and solo developers alike.
Executing TypeScript code typically involves transpiling it down to vanilla JavaScript for use in common environments like Node.js or the browser. This approach still represents the vast majority of how TypeScript programs are run, but a few projects have emerged that allow developers to run their TypeScript code directly.
tsm is a brand-new player in this category and represents a step forward in the broader TypeScript/JavaScript ecosystem.
tsm is a TypeScript module loader for Node.js, created by Luke Edwards. It expands Node.js to provide native TypeScript support without the need to transpile it to JavaScript first.
Rather, tsm uses esbuild under the hood to quickly transpile TypeScript sources into JavaScript on the fly before passing it to the Node.js runtime. This approach essentially abstracts away the typical transpilation step, making it transparent to the user.
The primary and most obvious advantage to using tsm is that developers don’t need to worry about TypeScript transpilation. This means that development feedback loops are shorter, build tooling is simpler, and deployment is more straightforward. This is particularly convenient for small projects like one-off scripts.
Because tsm runs on top of Node.js, developers familiar with Node will find using tsm natural and easy to incorporate TypeScript into their projects with a simple step.
For example, esbuild has built-in source map support, which means that TypeScript programs that run under tsm can be debugged with the standard V8 debugging protocol (included with Node.js) and popular debugging tools like VS Code.
Additionally, the vast ecosystem of npm packages and Node built-in APIs are available to TypeScript running with tsm.
One relatively small trade-off of using tsm is that it must be installed, in addition to Node.js itself, on the system that needs to run the TypeScript code.
This can be an inconvenience if distributing scripts meant to be run directly from the shell (like when using tsm as the interpreter for a script via shebang interpreter directive), but not a problem for fully packaged Node.js modules.
Other than that, there aren’t too many downsides to giving tsm a try, assuming there’s an appetite for new and emerging (and therefore, potentially changing) tech.
Unlike other elements of a project’s technology stack (such as databases, programming languages, frameworks, etc.), the nice thing about JavaScript build tools is that they can be swapped out later with minimal impact on the application’s source code itself.
There are a few different ways to hook tsm into a Node.js project.
node
executableAssuming you have tsm installed globally (via npm -- global install tsm
or yarn global add tsm
), you can run TypeScript files using the tsm
executable, like so:
tsm index.ts
For local installations, the tsm
executable can be found at ./node_modules/.bin/tsm
.
Note that any command-line flags will be passed through to node
, which is convenient for experimental features, debugging configuration, and the like.
Because tsm includes an executable, it can be used in a shebang directive like any other script interpreter. Shebang directives are formatted as such: !#<path/to/interpreter> [arguments]
.
They appear at the first line of the file and tell the operating system which program to use to parse and execute the rest of the file.
For example:
#!/usr/local/bin/tsm function print(message: string): void { console.log(message); } print('hello from TypeScript!');
--require
or --loader
hooksIf you still need to use node
directly rather than the tsm
executable, you can use the --require
or --loader
hooks to instruct node
to use tsm
to load TypeScript files. tsm needs to be installed as a local dependency (rather than globally) for this to work.
node --require tsm index.ts
node --loader tsm index.ts
tsm isn’t the only way to achieve transpilation-less executable TypeScript. Ryan Dahl, the creator of Node.js, has released a project called Deno that ships with TypeScript support out of the box.
Like Node.js, Deno is built on top of the V8 JavaScript engine and seeks to overcome some of Node.js’s design flaws.
Like Node.js and tsm, Deno can be used directly as an executable:
deno index.ts
It can also be used in a shebang directive:
!#/usr/local/bin/deno ...
However, code written for Node.js in TypeScript may not be portable to Deno, as Deno provides its own standard library as a replacement for the Node.js APIs. It also has its own paradigm for distributing modules rather than utilizing npm. Check out Deno’s standard library and API docs for more details.
tsm is a great way to integrate TypeScript into a Node.js project quickly and seamlessly. Because it’s built upon Node.js, tsm users can leverage the vast ecosystem of packages in npm and the powerful Node.js APIs, all from within TypeScript without needing to set up a complicated build process.
Check out tsm’s GitHub repo and its dependents list to see what people are using it for. Some notable examples include:
In short, use tsm when you want to leverage Node’s vast ecosystem from within TypeScript or integrate TypeScript into an existing Node codebase. If you don’t have many npm-only dependencies and want to enjoy the benefits of Deno’s security model, consider using Deno for your next server-side TypeScript project.
Happy coding!
LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page and mobile apps.
Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third-party services are successful, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens while a user interacts with your app. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.
LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. Start monitoring for free.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowExplore use cases for using npm vs. npx such as long-term dependency management or temporary tasks and running packages on the fly.
Validating and auditing AI-generated code reduces code errors and ensures that code is compliant.
Build a real-time image background remover in Vue using Transformers.js and WebGPU for client-side processing with privacy and efficiency.
Optimize search parameter handling in React and Next.js with nuqs for SEO-friendly, shareable URLs and a better user experience.