Built on typescript-go
RunTypes does not reimplement TypeScript. It is built directly on top of typescript-go, the native Go rewrite of the TypeScript compiler (the same one shipping as TypeScript 7, run from your terminal as tsgo). When RunTypes reads your types, it asks that compiler, so the answer is exactly the answer TypeScript would give.
A superset, not a dialect
RunTypes adds a layer on top of TypeScript. It never changes the language underneath.
- Anything that works on typescript-go works with RunTypes. Your types are resolved by the same checker
tsgouses, so whatevertsgounderstands, RunTypes understands in exactly the same way. - 100% compatible. There is no special compiler flag to switch on and no schema dialect to learn. Point the plugin at your existing
tsconfig.jsonand your types are the schema. - A strict superset. You keep everything TypeScript already gives you, and on top of it you get runtime functions generated from those same types: validators, JSON and binary serializers, mock data and reflection.
The whole compiler is in the box
The RunTypes binary loads your tsconfig.json, builds the same program tsgo would build, and runs the same type checker. The complete compiler lives inside it.
You can see the exact compiler revision it carries:
$ npx ts-runtypes-bin --version
ts-runtypes 0.1.0 (tsgo v0.21.1)
The value in parentheses is the pinned typescript-go revision the binary was built against (your exact numbers will differ per release). Your types are read by a real, known version of the TypeScript compiler, never an approximation of it.
You could compile with it, but that is not the point
Because the full compiler is embedded, the binary could in principle type check or even emit JavaScript for your whole project, the same way tsgo does. We deliberately do not do that.
Compiling and type checking TypeScript is tsgo's job, and it already does it well. RunTypes has a single job: take the compiler's understanding of your types and turn it into runtime code. We borrow the type system, we do not try to take over your build.
build or tsc style command. It reads your types and emits runtime functions. Keep running tsgo (or tsc) for your build exactly as you do today.Current status: a preview compiler, two passes
Two honest caveats, both rooted in where the Go compiler is today.
typescript-go is still a preview. TypeScript 7, the native compiler, is under active development and is not yet the stable default. RunTypes tracks it as it matures, so the occasional rough edge comes from the foundation still being in preview.
For now, RunTypes runs as a second pass. The hook that once let runtime libraries plug into the compiler was never ported to the Go compiler (microsoft/typescript-go#516), and there is no supported way to run inside it yet. So today tsgo and the RunTypes binary are two separate processes: your normal build runs tsgo, and the plugin runs our binary alongside it. Each one builds its own view of the project, which means your files are read twice, once by tsgo for your build and once by RunTypes for the generated code.
That second pass is a real cost, and it is a current limitation rather than the destination. If the compiler ever exposes a supported extension point, RunTypes would fold into a single pass. Until then the extra read stays where it belongs, at build time, and nothing about it reaches your runtime bundle.
See About RunTypes for the design decisions behind all of this, or jump to the Quick Start to wire it up.