Video wird geladen...
Video konnte nicht geladen werden
I wrote a 2D game, entirely in type-level Typescript. Yes, you read that right. This is flappy bird, written only in Typescript types. How did I do it? It involves a lot of type magic, and a new type-level Typescript runtime I made in Rust + Zig. Let me... show more
625,414 Aufrufe • vor 2 Jahren •via X (Twitter)
11 Kommentare

First off, type-level Typescript can be thought of as a purely functional programming language, where everything is immutable. So we can't have some global game state (bird position, pipes, etc.) and mutate it What we can do is use functions to return a new, updated game state

So each frame, we pass the game state through a series of updates that need to happen each frame: handling jumps, applying gravity to the bird, moving the pipes. The end result looks something like this, and its a surprisingly elegant, linear, pipelining of functions:

The next part is rendering. I drew inspiration from modern graphics APIs and added a command buffer to the game state: basically a list of drawing commands Each frame, we update the game state, and populate the draw command buffer. In the end even rendering becomes elegant too:

Okay, that's the type-level logic. But in the video, the game is running in the browser, how does that work? This where some hardcore programming comes into play.

The basic rundown is that I created a type-level Typescript runtime, allowing types to be run outside of the Typescript compiler/language server. It's made of two parts: 1. A compiler in Rust to convert Typescript types -> bytecode 2. A custom VM in Zig to execute that bytecode

I then compile the runtime to Wasm, and each frame it takes the draw commands from the game and executes them using the web canvas API. And that's the basic overview of how I made flappy bird in type-level Typescript! More detail in this blog post:

But that's not all. By creating this runtime, I also accidentally created probably the fastest and most complete type-checker for Typescript, but types only.

My hope is that by focusing on nailing down type-checking type-level Typescript first, which is a way easier task than all of Typescript, the runtime can be useful very quickly. Check out the source here: And play the game here:

And here is the final Typescript code for the game, if you wanna check out my unholy type-level trickery. It's actually not that bad, just the moving pipe logic and the collision with pipe logic is unsightly because it needs to do iterative recursion

You should definitely make a video about this if you haven't already

great idea, probably gonna use @Remotion or @fframes_rust for making the visuals!



