I wrote this because I was frustrated by the recent "16 AI Agents build a C compiler" narrative. Building a C compiler is an exercise in implementation; I wanted to see if one dev could use AI for invention.
The result is TJS. It's my attempt to fix what I dislike about TypeScript (erased types) and solve the eval() problem for AI agents. It treats JS like the Lisp it was meant to be: types are real values, autocomplete works by introspection, and execution is strictly gas-metered.
The playground is live here if you want to test the sandbox or the types: https://platform.tosijs.net
Happy to answer technical questions about the compiler architecture, the AJS sandbox, or how the gas metering works.
I am in Finland so apologies in advance if I am slow to reply.
The tjs compiler transpiles ts into itself: https://platform.tosijs.net/#example=Hello+TypeScript§io...
It's written in typescript and can transpile itself.
When it transpiles typescript, type declarations become contracts, and types are available at runtime.
It does all this with a 50-70% overhead (imperceptible in most cases), but there's an unsafe escape hatch (!) => {} functions bypass type checks.
Oh yeah, it does inline WASM and it handles the hard stuff other WASM implementations kind of leave as an exercise -- moving data across. And it support SIMD.
https://platform.tosijs.net/#view=tjs&example=Vector+Search+...
Error propagation is monadic, so functions passed bad arguments just don't execute. Also functions know from whence they came and you can execute code in debug mode and get a trace with your monadic error, so it's very agent friendly.
If you code in tjs natively you can do inline tests of unexported functions at transpile time.
If you transpile ts using tjs it gives you the same capability.
Single pass transpilation does inline tests and generates documentation at the same time.
tjs itself is a TRUE js superset with predicate functions to handle complex types (if your type system is going to be turing complete, own it), full introspection (so it's a true LISP, or what Dylan aspired to be), and safe Eval using a language subset that is deeply async. Again, universal endpoints.
Simple types are declared by example, so:
function greet(name: 'Alice') -> 'Hello, Alice' => `Hello, ${name}`
is not just a declaration of a function that takes a string and returns a string, but the string should look like 'Alice' and if it is 'Alice' the function will return 'Hello, Alice' and this is also an inline test that runs at transpile time.
What does that mean?