Why TypeScript now — and when I'd reach for Rust, Go, or C++
A question I keep getting: is the stack good, or should the whole thing be rewritten in a faster language? The honest answer is that for what this software does today, TypeScript isn't a compromise — it's arguably the best fit. The other languages have a real place, but at the edges.
Someone asked a fair question: the operator console is written in TypeScript (a language that adds strict type-checking on top of JavaScript) — is that good enough, or should the whole thing be rebuilt in something faster like Rust, Go, or C++?
Short answer: for what this software does today, TypeScript isn't a compromise — it's the right tool. The faster languages have a real place, but at the edges, and only when a concrete need pulls them in. Here's the reasoning, in plain terms.
What the software actually does right now
The thing I'm building is a ground control station — the console an operator uses to command uncrewed vehicles (drones, ground robots, boats). Right now that's four things: a user interface, a model of the domain (assets, commands, missions), the safety pipeline every command passes through, and the plumbing that ties them together.
None of that is number-crunching or squeezing microseconds. It's logic and screens. And for logic-and-screens, the qualities that matter are: catching mistakes early, moving fast, and expressing rules clearly. Dun mismo magaling ang TypeScript (that's exactly where TypeScript shines).
Why TypeScript is the right core (not a fallback)
Three reasons, each tied to what makes this project distinctive:
- The safety is built into the type system — and that's the whole point. The most important rule in the system is that a weapon-style command literally cannot be created without an authorization approval attached. In TypeScript, that's enforced by the compiler before the program ever runs — it simply won't build if you try. Go can't express that kind of rule at all; C++ makes it awkward; Rust can, but you'd move much slower. TypeScript gives me that guarantee for free.
- One language from the screen to the logic. The interface and the domain share a single model, so a change flows through cleanly and mistakes surface immediately. Mixing a Rust or Go core with a separate UI language would add friction I don't need yet.
- Speed of iteration, before there's a product. At this stage the goal is to prove the shape of the system and get to a working demonstration. Raw execution speed would buy nothing at this layer.
Rewriting the console in another language would throw away my biggest advantage — the compile-time safety — to gain performance the console doesn't need.
Where TypeScript does hit a wall
This isn't blind loyalty. There are places the runtime underneath TypeScript — Node.js — genuinely struggles, and those are exactly where a different language earns its keep:
- Very fast, steady data loops — decoding a radio link many times a second, or moving high-rate sensor traffic. Node.js pauses briefly to clean up memory (garbage collection), which is fine for a UI but not for a hard real-time loop. Rust or C++ fit there.
- Reading data off an untrusted link. Parsing raw bytes that an attacker could reach is the classic place a bug becomes a break-in. Rust is memory-safe — the compiler prevents that entire category of bug — which makes it the right choice for that job.
- Talking to existing hardware and industry systems — radios, and the middleware defense systems use to move data around. That world is written in C/C++, so you link to it there.
- Networking services and gateways — the glue that connects many systems. Go is excellent at this: simple, concurrent, and it compiles to a single self-contained file that drops neatly onto an isolated machine.
The rule: add languages, don't switch — and only at a trigger
The key discipline is when, not whether. Adding a second language isn't a free upgrade — it means more build complexity, more skills required, and more surface to secure. So the plan is deliberate:
- Stay entirely in TypeScript through the rest of the core (the safety pipeline, the flight recorder, the encrypted link) and the first real customer use cases. All of those are well served by it.
- Introduce the first non-TypeScript piece only at a concrete trigger — realistically Rust, the first time I build a hardware-link decoder or the encryption core, because memory safety is the reason.
And crucially, none of this is a rewrite. The system is built in independent sections that talk through fixed contracts — so a Rust decoder or a Go gateway can be added later as its own piece, plugged into the existing seam, without touching the console at all. That's the architecture doing its job: it lets me pick the best language per part, later, instead of betting the whole thing on one choice now.