Loading video...

Video Failed to Load

Go Home

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...

625,414 views • 2 years ago •via X (Twitter)

11 Comments

zack (in SF)'s profile picture
zack (in SF)2 years ago

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

zack (in SF)'s profile picture
zack (in SF)2 years ago

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:

zack (in SF)'s profile picture
zack (in SF)2 years ago

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:

zack (in SF)'s profile picture
zack (in SF)2 years ago

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.

zack (in SF)'s profile picture
zack (in SF)2 years ago

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

zack (in SF)'s profile picture
zack (in SF)2 years ago

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:

zack (in SF)'s profile picture
zack (in SF)2 years ago

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.

zack (in SF)'s profile picture
zack (in SF)2 years ago

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:

zack (in SF)'s profile picture
zack (in SF)2 years ago

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

Ninja's profile picture
Ninja2 years ago

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

zack (in SF)'s profile picture
zack (in SF)2 years ago

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

Related Videos