TypeScript without Build Tools
TypeScript without Build Tools êŽë š
TL;DR
There are a bunch of tools these days that allow you to write in TypeScript and⊠just not think about it much more than that. You neednât deal with converting that code into JavaScript yourself.
Hereâs what has me thinking about all that.
Weâve got a monorepo at work.
Weâve been moving to TypeScript for years, with mostly positive results. Iâm fairly convinced that the code output from writing in TypeScript is better and the experience of writing and editing existing TypeScript code is better DX.
Itâs not without challenges though. I hate wasting time futzing with types when I just know it really isnât improving the quality of my code Iâm just fighting with a machine. This concern is multiplied when you see your team doing the same thing.
Another challenge is the part where you actually have to produce JavaScript. This is not a difficult job in and of itself. There are loads of tools that do this from the canonical tsc
to tools that do no type checking but can very speedily compile TS to JS (like esbuild). But sometimes, you still have to do it.
One example from our monorepo is that we have some components that weâd like to write in .tsx
, but they can be consumed by a number of different site building tools (e.g. a Next.js site, an Astro site, an classic Just Load React On The Page site, etc). The most sane way of handling this is processing the TS into JS ahead of time. That way whatever site that wants to import them can do it as native, normal JavaScript ESM stuff.
monorepo
website-1
website-2
packages
components
dist
MyVeryImportantComponent
index.js
src
MyVeryImportantComponent
index.tsx
Now I need to make a build process to do this. Iâll probably write a little script. npm run process-packages
or whatever, fine. Iâll probably use tsc
for this on purpose, knowing that it isnât the fastest, but itâs the one that is capable of actually throwing errors when there are TypeScript problems. This is useful because I can call my script in a pre-commit hook in Git, for example, to prevent myself and my team from committing bad TypeScript. I can call the script in CI as well which is additional protection.
So now I have tsc
building from src
to dist
, great. But TypeScript explicitly will never build an âother filesâ copy machine (Microsoft/TypeScript
). Well thatâs annoying. What about my other stuff?
packages
components
src
MyVeryImportantComponent
index.tsx
queries.graphql
styles.module.scss
Now I have to wire up some new machine to copy anything that isnât TypeScript over from src
to dist
. Blech. Fine, Iâll do it.
But this is all complicated by the fact that this script weâre building needs to be able to run two ways:
- As a builder, where you call it and it does the job
- As a watcher, where it runs the build when any pertinent file changes
Itâs unacceptable DX to expect a developer to run a build command after every file change manually. So we have to build our own little watcher too. I guess itâs paulmillr/chokidar
time? I hate piling on dependencies, but thatâs the only watcher thatâs ever felt truly reliable to me.
I donât mean to paint this picture too negatively. This is all doable. This is the job. There are tools to help with this that get better over time. But wow, itâs a lot when you consider it was just TypeScript, this invisible layer of special code helping syntax, that pushed us this far into toolsville.
Iâd rather focus on the positive stuff Iâm seeing here. As the years tick by, and TypeScripts popularity remains high, the surrounding tools that deal in JavaScript are more and more fine with âjust leave it as TypeScript.â I find that interesting!
This ânativeâ support of TypeScript is a product choice. We know some of our customers write and prefer TypeScript so weâll make it easier for them. But there is no Officialâą way to do this. The product needs to decide how they are going to handle it. Are they going to check types for you and alert you (somehow? somewhere?) to type problems? Or are they leaving type problems to you, and if the code compiles to JavaScript, so it shall be. What version of TypeScript is it going to support? Is configuration necessary?
So what are these products?
Tools & Products That Let You Write TypeScript âNativelyâ
Frameworks
- Astro: âAstro ships with built-in support for TypeScript. You can importÂ
.ts
 andÂ.tsx
 files in your Astro project, write TypeScript code directly inside your Astro component, and even use anÂastro.config.ts
 file for your Astro configuration if you like.â - Next.js: âNext.js comes with built-in TypeScript, automatically installing the necessary packages and configuring the proper settingsâ
- This is pretty common in UI meta frameworks⊠Nuxt, Remix, SvelteKit, Redwood, etc. This, likely, is the thing that pushed other products to do the same.
Runtimes
- Deno: âTypeScript is a first class language in Deno, just like JavaScript or WebAssembly.â You can just
deno run script.ts
, deploy.ts
files to their cloud service, and there is a type checking command. See what I mean about it being a product choice? - Bun: âBun treats TypeScript as a first-class citizen.â
- Cloudflare Workers: âTypeScript is a first-class language on Cloudflare Workers.â
Bundlers
- Vite: âVite supports importingÂ
.ts
 files out of the box.â - esbuild: ââŠesbuild has built-in support for parsing TypeScript syntax and discarding the type annotations.â
- Parcel: âParcel supports TypeScript out of the box without any additional configuration.â
Meta
- tsx: The big thing here is the tsx project, or âTypeScript Executeâ. A lot of times what youâre trying to do in Node is
node script.ts
, like in an npm script, but you canât, because Node doesnât support TypeScript ânativelyâ. But replacenode
withtsx
, and it works.
Drumroll?
I started writing this post a few weeks ago, and now Iâve just seen: Node.js Now Supports TypeScript By Default.
totaltypescript.com
Node 23 will soon be able to run TypeScript files without any extra configuration.
You can runÂ
node index.ts
 with no further flagsNode will strip out the types using a version ofÂ
swc
, then run the resulting code.
Well there ya have it. Feels like we were on to something there eh?
I feel like this pushed it more into Officialâą territory and now this will be less of a product-level choice and more of a âleverage what the technology already doesâ choice. For instance, products donât have do anything special or build additional technology to support TypeScript, theyâll just do what Node does. And they wonât have to fret over âwell should we do type checking?â because they can just follow in the steps of what the tool already does (just strip them).