969: This Guy Is Nuts ![rw-book-cover](https://wsrv.nl/?url=https%3A%2F%2Fmegaphone.imgix.net%2Fpodcasts%2F5197fe5a-42f7-11f0-affd-87d9985a1760%2Fimage%2Fc86a54acd72683732c4773e25bf0ae14.png%3Fixlib%3Drails-4.3.1%26max-w%3D3000%26max-h%3D3000%26fit%3Dcrop%26auto%3Dformat%2Ccompress&w=512&h=512) ## Document Notes ## Highlights - **Building Doom Inside TypeScript Types** - Dimitri attempted Doom purely in TypeScript types to test whether the type system could actually run a full program rather than just being 'Turing complete' mathematically. - He expected it to fail quickly but the project grew into a year-plus effort culminating in a successful boot demonstrating extensive type-level encoding. Transcript: Wes Bos This is literally, to preface this, this is absolutely nuts that you did this. Dimitri Metropolis And anyone listening should like buckle up. So go ahead. I wake up sometimes in the morning and I think to myself, like it's been a year since that was complete more. And I sometimes think, wake up and I think, I wonder if it's possible. And that's probably the best way to explain it. It's a thing that you would think something like that about. You just like, it's, I had this nagging thought. I wonder if it's possible. And actually almost, I mean, basically the entire time, I thought it wasn't possible. So what's the what? The what is, Doom is a game, you know, it shows pixels on your screen, you type, you push keys on your keyboard and things happen inside the game engine. Okay, like abstractly, that's what it is. And TypeScript is, you know, people have to separate the type system and the runtime language we call JavaScript. So like when I say TypeScript, I'm talking about the thing that's running on top of JavaScript, the types. So the question is, can Doom the game run in TypeScript types? Just the type system. No, absolutely no JavaScript whatsoever. Not a single line. The DTS file is zero bytes. Yeah, no JavaScript. Wes Bos So to be clear, this is not you writing like a canvas and running Doom in the browser. TypeScript, I don't think a lot of people understand this. TypeScript is a language, right? It's not, obviously it's something that converts to JavaScript, but TypeScript itself, the types, that's its own programming language, right? Yes. Dimitri Metropolis So the type system has been known to be like mathematically Turing complete for many years. And this is something I have a big issue with actually. So people talk about this concept of like mathematical Turing completeness. And I think it's baloney. I think, like, imagine I told you I have this thing and it's Turing complete, except it takes longer than the heat death of the universe to calculate one plus one. Is that interesting? Like, I guess to mathematicians somewhere out there, it's interesting, but to me, it's not interesting. Yeah. And I've come to realize, actually skipping ahead to the end, I've come to realize after I released it, some people educated me a little bit. Doom itself, the game is Turing Complete. Like there's a way you can set up a level with like different doors and gates and things that you can make a Turing machine. And so like actually Doom Complete is the better metric because if it's Doom Complete, it's also Turing complete. But we're getting in the weeds. The big picture is how do you even show, uh, you know, typescripts are just like strings and text. How do you even show it? And so these are the questions that I had in the beginning that I'm like, oh, okay. Uh, people say that, you know, oh, it's well, it's turing complete. So it should be, you know, it can run anything. And I just think that's wrong. I think it's like, it can't run doom. And I thought, all right, I'll find a way to show why TypeScript types cannot run Doom. And that's going to be the project. So I thought it'd be like a two week project. I didn't think it would be this long, like year long, like section of like my life. ([Time 0:01:35](https://share.snipd.com/snip/a8f00ad5-fe79-40fc-af84-2e69d4912f29)) - **Rendering Pixels As ASCII Art With Types** - Dimitri rendered Doom output as ASCII/UTF pixel art by mapping character pairs to grayscale shades and creating a gradient of characters to approximate pixels. - He first validated control by drawing a small heart purely with types before scaling up to the full frame rendering. Transcript: Dimitri Metropolis Art that's turned into text. Like, you know, people call it ASCII art. I've also learned it's not technically ASCII art because you use characters outside of the ASCII 128, whatever. I call it ASCII art. Yeah, yeah. UTF art isn't as cool. So people draw pictures with monospace characters. And if you think about it, you know, a character, a monospace character is the aspect ratio of that rectangle is roughly like two blocks high and one block wide. And so if you take two of those, then you have like a square. Okay. Now, think again. Okay. Well, like different things I could put in those two boxes constitute like an average number, like an average color. Like if you have white text on a black background, it's like an average color. And so like from there, you can kind of calculate like, okay, I'm going to create like shades. I'm going to create pixels of, you know, going from totally black, which is just spaces and totally white, which like there's a character that's like a square. You can just put them next to each other. And then I'm just going to create like a gradient in between there. And now I have like, you know, 256 colors, like a gray scale picture that I can start to draw. If you kind of like zoom out far enough, you can see an image. ([Time 0:05:10](https://share.snipd.com/snip/aa7f1e57-e43f-45fb-9137-27725ac5408d)) - **Compilation Marathon And The Final Run** - The final successful TypeScript type-only run to boot Doom took about 11.5 days of compilation, after many multi-day failed attempts during a year-and-a-half project timeline. - Dimitri set a one-month practical cutoff for runs but kept iterating until the Halloween-night success. Transcript: Dimitri Metropolis Or what does it actually look like? Yeah. The final run happened in 11 and a half days. It was actually the night of Halloween. My kids were like, you know, come on, dad, we got to, like, let's go. And I'm like, I just want to like start one because by that point I had run it. I have all the stats. And so I have to say as a preface to this, I've been working on it forever, but I've been very busy with other things, but I'll be putting out a video explaining the whole story. It can be like a very long video, but I had been running it and failing constantly and constantly failing. So like there were multiple runs that lasted many days before the final one. And I was able to figure out roughly how long it would take. And my cutoff was a month. I was like, as long as it takes less than a month, I had a computer in my basement. It's like constantly doing like running TSC in a loop, doing the type checking. Like as long as it takes less than a month, I think it's cool. So that was the final run. ([Time 0:07:00](https://share.snipd.com/snip/b09c9a3e-98a7-42b1-b2c3-5bb5e22987ab)) - **Use TypeSlayer To Diagnose Type Costs** - Use TypeSlayer to expose and inspect TypeScript's internal type graph so you can find runaway unions, heavy types, and diagnostics causing slowdowns. - The tool highlights costly types and 'complexity limit' errors so you can fix hotspots rather than hiding diagnostics with ignores. Transcript: Dimitri Metropolis Totally. TypeSlayer is a tool, like you said, for diagnosing TypeScript performance problems. And again, when I say TypeScript, I don't mean like JavaScript, I mean the type system. And it was born directly out of the Doom project. So in order to do that, make that Doom project happen, the hardest part was performance. The hardest part is like, how do you even, it's like a lot of data. It's, you know, like, I think it was like 177 terabytes of TypeScript types in the end. So like, and not all of that was ever stored at one point. You know, it's in memory on my computer and like, I have to clear it and there's like things I had to do. But when I started looking more about how you even go about diagnosing what TypeScript is doing under the hood, it's really hard. I mean, it's prohibitively hard for almost everybody. I mean, there's a process where you can generate these JSON files and there could be hundreds of... I was saying hundreds of megabytes until recently, but now I released TypeSlayer and people are sending me their five gigabyte type JSON files where they have monorepos with 3000 packages, You know? Um, and they need eight, you know, uh, one person, not 80. It was, uh, they said they need 60 gigs of memory to type check their project. Okay. So that's like not normal. Let's say. Wes Bos How, how big are these, these projects is like, we had the types of folks on and they, yeah, they, they told us like, they're allowed to talk about some of the projects. Um, and then off camera, they tell us about some of the other big projects that they're like many, many millions of lines of code that takes 60 gigs of Ram to just type check it. Yeah. Dimitri Metropolis Um, so the thing is, that's interesting. And so I've, I've been in the position since I did doom, you know, like I have to stress to people listening, it's all fun and games with the doom project, but what I really hope that people Take away from like these projects text layer is one of them. Personal projects are so like, so overpowered for creating knowledge that you can apply in a very expert way at work. Like you just, you cannot, you can like definitionally cannot get the experience that would really push you and propel you forward at work because at work, your job is to take things Off the shelf. I mean, you should not be reinventing the wheel, but in order to really understand the wheel, sometimes you do need to go into the woodshop and make a wheel. And even if it's just a toy, like you're going to come out of that with knowledge. So I came out of the Doom project with a lot of knowledge and I applied it at my company. And it was interesting. Like I found problems that solved like, you know, would take like one of them. I took a hundred seconds off the CI by basically a five line fix. Wow. And how does that happen? And the reason it happens usually, I think one of the big reasons is like you do something accidentally. You use some typefest utility or some, I'm not trying to pick on typefest, but like you use some abstract TypeScript type level modifier and you don't really realize what it's doing. And, or maybe it's just not good under the hood. And it creates this explosion of types. You have your like, usually there's like a matrix multiplication of two types that creates this like runaway train. And, you know, TypeScript has to go do all that work to kind of like figure all those combinations out. And it doesn't show you that though. It's all under the hood. So like the thesis with TypeSlayer is let's expose the guts. Let's show people what under the hood. Let's show people what, you know, you want to see the biggest union in your project. Like it tells you, you want to see the type that's most frequently the part of the most number of unions. It'll tell you, you want to see like whatever it is, you want to see. ([Time 0:10:24](https://share.snipd.com/snip/6267df03-1295-4cf6-a585-ce1a7b2e9b7f)) - **Hidden Memory Costs In TypeScript Monorepos** - Extremely large projects can produce enormous type-state and memory footprints (multiple gigabytes) that are invisible without tooling. - Dimitri found monorepos producing multi-gigabyte type JSON and projects requiring dozens of gigabytes to type-check. Transcript: Dimitri Metropolis The hardest part is like, how do you even, it's like a lot of data. It's, you know, like, I think it was like 177 terabytes of TypeScript types in the end. So like, and not all of that was ever stored at one point. You know, it's in memory on my computer and like, I have to clear it and there's like things I had to do. But when I started looking more about how you even go about diagnosing what TypeScript is doing under the hood, it's really hard. I mean, it's prohibitively hard for almost everybody. I mean, there's a process where you can generate these JSON files and there could be hundreds of... I was saying hundreds of megabytes until recently, but now I released TypeSlayer and people are sending me their five gigabyte type JSON files where they have monorepos with 3000 packages, You know? Um, and they need eight, you know, uh, one person, not 80. It was, uh, they said they need 60 gigs of memory to type check their project. Okay. So that's like not normal. Let's say. Wes Bos How, how big are these, these projects is like, we had the types of folks on and they, yeah, they, they told us like, they're allowed to talk about some of the projects. ([Time 0:10:41](https://share.snipd.com/snip/9e934801-c93b-4807-bb89-b4607e0e7d57)) - **Triage Type Performance With Small Fixes** - Use small, targeted fixes identified by tooling to shave seconds or minutes off CI and editor responsiveness rather than assuming big rewrites. - Investigate utility types or matrix-like type operations that can cause combinatorial explosions and optimize or replace them. Transcript: Dimitri Metropolis Personal projects are so like, so overpowered for creating knowledge that you can apply in a very expert way at work. Like you just, you cannot, you can like definitionally cannot get the experience that would really push you and propel you forward at work because at work, your job is to take things Off the shelf. I mean, you should not be reinventing the wheel, but in order to really understand the wheel, sometimes you do need to go into the woodshop and make a wheel. And even if it's just a toy, like you're going to come out of that with knowledge. So I came out of the Doom project with a lot of knowledge and I applied it at my company. And it was interesting. Like I found problems that solved like, you know, would take like one of them. I took a hundred seconds off the CI by basically a five line fix. Wow. And how does that happen? And the reason it happens usually, I think one of the big reasons is like you do something accidentally. You use some typefest utility or some, I'm not trying to pick on typefest, but like you use some abstract TypeScript type level modifier and you don't really realize what it's doing. And, or maybe it's just not good under the hood. And it creates this explosion of types. You have your like, usually there's like a matrix multiplication of two types that creates this like runaway train. And, you know, TypeScript has to go do all that work to kind of like figure all those combinations out. ([Time 0:12:16](https://share.snipd.com/snip/1648ff1e-9fa9-4d3f-bad4-c754ab6bee15)) - **Learn Deeply Through Unconstrained Projects** - Do personal, experimental projects to gain deep knowledge you can't get from day-to-day work because they force unfamiliar problems and learnings. - Dimitri credits Doom and TypeSlayer with practical insights that produced impactful fixes at work. Transcript: Dimitri Metropolis Like you just, you cannot, you can like definitionally cannot get the experience that would really push you and propel you forward at work because at work, your job is to take things Off the shelf. I mean, you should not be reinventing the wheel, but in order to really understand the wheel, sometimes you do need to go into the woodshop and make a wheel. And even if it's just a toy, like you're going to come out of that with knowledge. So I came out of the Doom project with a lot of knowledge and I applied it at my company. ([Time 0:12:26](https://share.snipd.com/snip/109c37fb-9df6-4653-ace6-833397d47070)) - **Build Native Tools With Tauri And Cross-Build** - Prefer Tauri (Rust) for GUI tooling that needs native capabilities, small static binaries, and large-memory handling instead of Electron or browser-only approaches. - Ship platform-specific native binaries in CI, and install the right one at post-install to avoid massive multi-platform bundles. Transcript: Dimitri Metropolis Think it's been awesome. I mean, I wasn't sure if it would I mean, there's something that's emerging now that I'm seeing more projects do this. Like Redwood JS has this, I think Turbo Pack just released something where you run a CLI and it opens up a local host tab in your browser to show you some like fancy UI about your app. And I'm really excited that people are kind of catching on to this idea because I just do not like CLIs at all. I've actually been on CLI team. We just finished recording a podcast. We're like, what's the hype on TUIs? I love a terminal app, but buttons are good. I previously worked at Vercel and I worked on Turbo Repo and I didn't do a lot of the work. Chris, my colleague did, but we implemented a 2E in TurboRebo. And a lot of people were very excited about it. And I'm happy for them, you know, but can they be happy for me too? I'm not excited about these things. And so I've always been a user of like GitKraken. I've always been, I use like Yak and I used to work on Insomnia, which is, you know, Yak and Insomnia are both kind of like postman alternatives tools. Yeah, Yak is cool. Yeah. So, you know, how is it that I, you know, get my job done with all of these CLIs? I have trouble with it. So what I did is I made this proof of concept called Instant Tari. So you can go NPX Instant Tari anywhere right now. And it opens up Atari app. And it's just a nice little, it's like nine megabytes. Okay. It's not, these are not big apps. And something I think I want to stress to people about CLIs that they may not think about is for websites, we discuss this concept of bundles a lot. We're like, oh, if I, if I, if I bundle the app and you might have lots of other things. So if you, you pull in a dependency that has Lodash, but somewhere else had Lodash, it's like a negative, it's like a net nothing to add this product that uses Lodash. But when you have a thing like a CLI, all of the node modules come in, it becomes like this black hole and, you know, very massive situation. But with Tari, you deliver to your end users a static binary. And that's all. They just run the binary. There is no other junk in there. And so it's like nine megabytes for everything. And that's very fast to download. Much faster than, you know, MPX for, you know, some CLI for node modules. ([Time 0:16:40](https://share.snipd.com/snip/c115cfbd-dfdd-4d3d-8a64-660412b127bc)) - **Performance Impacts Editors, CI, And AI** - TypeScript performance affects three key loops: CI speed, editor responsiveness, and AI/agentic tooling that analyzes code. - Faster type systems unlock productivity and make automated agents more practical for large codebases. Transcript: Dimitri Metropolis It looks like is important? Absolutely. And I mean, this was one of the biggest motivations for the, not, performance was the reason for TypeScript, you know, moving to go, right? But like beneath, you know, as a sub point beneath that, why does performance matter? You know, there's really three things. The first two, everybody's familiar with. Number one is how long it takes to run your CI, right? You're going to be blockaded on your CI by a long type check because everybody is going to want to type check before they'll submit a, you know, merge a PR. The second thing is how it works in your editor. Like, you know, we've all had this experience where you're trying to like, you hover over something and it feels like you'd need to go get a cup of coffee before it'll come back, you know? Like that's a very painful experience and slows you down. The third thing is the new one, this agentic programming situation where you have agents going out and doing work on your behalf. And they, just like you and your editor and just like on your CI, are beholden to the speed at which TypeScript can deliver them back information. And so it becomes a whole new world if the, you know, it's like almost instantaneous loop that you go through. And that's why it matters. And, you know, to some projects, it doesn't matter because they don't have a problem. And so I have to stress with a tool like this, you know, you may take your car to the mechanic and they say, it looks fine to me. And, you know, you just need a new oil change or, you know, whatever. And that's not a bad result. But for some projects, you really need that oil change. ([Time 0:24:40](https://share.snipd.com/snip/b6a4da7e-c677-477a-aa5c-25b6c36949ad)) - **Speed Reduces Pain But Doesn't Fix Bad Types** - A faster compiler (TSGo) reduces pain but can normalize longer compile times if users tolerate them, so visibility and fixes still matter. - Dimitri expects new speed to lower barriers but warns that inefficiencies will simply inflate to fill available budgets. Transcript: Dimitri Metropolis Okay. My personal opinion is it does not. And the reason is, over time, these kinds of problems will come up again. Have you heard of this thing where you, add a lane to the freeway? Yeah. And then, you know, just one more lane. Yeah. One more lane. And, you know, the types, I think they even talked to, in fact, maybe was it you guys that they, I saw that, you know, the team, the typescript team talking to about this concept. Daniel brings it up sometimes asking, talking about TSGO. I think that in the short term, it's going to relieve a lot of pressure. And I think it's going to make open a lot of opportunities. There are things like higher kind of types that are exciting and sort of interesting little tricks you can do in TypeScript that are not super duper feasible. Like I think effect has sort of figured it out, but it's not a great thing right now. But TypeScript Go kind of lowering that upper threshold is going to allow some cool new innovations in. But if you have a matrix multiplication that's creating hundreds of thousands of union members, and it takes 10 minutes, but it's 10 times faster. So now it takes one minute, but it should be zero seconds because it was just wrong. Like, is that really a win? It is a win. Yeah. But what's going to happen is that one minute is going to become acceptable. And then like, you know, that's the thing with like the exponential growth. You know, over time, I don't think it's going to be long before people are like, oh, TSGO is so slow. ([Time 0:27:51](https://share.snipd.com/snip/66fca8ce-0782-4298-8811-8c2f68c6a03a)) - **WASM Enables New Delivery And Runtime Models** - Dimitri implemented a WebAssembly runtime entirely within TypeScript types, showing types can model low-level systems when pushed far. - New WASM features (64-bit, multiple memories, exceptions) make shipping complex native apps via WASM more feasible now. Transcript: Dimitri Metropolis Mean if it's anything it's i would say it's probably wasm um i'm definitely very big on the wasm train type we you know we didn't get into the architecture but the the doom and typescript Types project was done by making a wasm runtime and actually the it can run other things. So a couple people have told me, you know, Dimitri, you really sold yourself short here by just talking about Doom so much. You built a full WebAssembly runtime in TypeScript types that can run. Oh, my God. It can run other programs, too. I just, you know, because of my mindset, I never thought Doom would be possible. And so, like, people have asked me, why did you go from nothing like this ever having been done, not even close, to like all the way straight, you drew a straight line to Doom. You didn't do like, you could have done Tetris and then like Pokemon, and you could have built up in smaller pieces. How did you go from nothing to Doom? And the reason is because I didn't think it was gonna work. So like, if your mindset is, I'm gonna find the thing that breaks all of this, why would you play around with Tetris or Pong or something, right? You just go straight to the thing that's going to be the hardest to show why it would fail under pressure. And so like WebAssembly has a lot I think to offer and there were reasons in the past not to use it. But in this past October we had a release where WebAssembly got a lot of stuff added to it. It has 64-bit memories, multiple memories. You can do things that were completely infeasible before, shared processes and other things, exception handling. And I think that the cat is out of the bag now. ([Time 0:34:50](https://share.snipd.com/snip/6ed8afc3-2f66-46b1-8e0f-062f120bab8d)) - **Exploring JavaScript 1.0 In A Win95 VM** - Dimitri inspected JavaScript 1.0 by booting a Windows 95 VM and running the original Netscape build to see how minimal the language was. - He found early JS lacked arrays, exceptions, and many core features, illustrating humble origins of major languages. Transcript: Dimitri Metropolis You? Yeah. Yes, please. There is a secret that I would like to expose in the JavaScript world. And I'm going to, I'll, I'll expose it now. Expose it. Yeah. But I, but I want to, I'm going to make a video with this. I'm actually, I was talking to, I won't say who, but I was talking to someone you'll, you'll all know about coming out and doing a video with this. JavaScript 1.0 is well known to have been kind of like, quote unquote, written in seven days. I don't think, I got curious one day and I spent way too much time finding a, I booted a Windows 95 VM, which is really hard to do on modern hardware, by the way. I thought it would just be like, you open up VirtualBox and get the image. No, it is challenging. Then I went even farther to connect it to the internet, which you need like Netscape Navigator version 2.001 gold or something. And I found like the first version of Netscape that shipped with the first version of JavaScript. And I booted and of course, like no web page runs. Like I think example.com I could get to come up because it's got like, you know, one HTML tag. But the point was, I wanted to see what I could run in JavaScript to see like, what is JavaScript 1.0 really like? Like, what is this thing that we've all heard was written in seven days? And can I tell you, there is almost nothing there. It did not have arrays. It did not have, yes, it does not have undefined. It doesn't have exceptions. It doesn't have like, it doesn't have lots of things that we think of as being completely core to the language. It doesn't have first class functions. You can't pass a function to another function. There's, it's, there's, there are so many things that are like absolutely critical to everything. It doesn't have switch statements. I mean, it's like what it was in version 1.0, if you actually go and use it was actually very close to nothing. I'm not trying to throw shade. I think it's actually awesome that it started at such humble beginnings, but I think like, it's really cool to like, so I got a whole dev environment going up where you have like notepad Open. Cause of course there's no like ID. And you can like run, I got the loop working where I could like save it and like run the file and we could see what happens. And there are just so many, like, you know, instead of arrays, what did they do? Well, you know, you just, you have objects. So, uh, and there wasn't, yeah, the object syntax is, uh, like missing, but anyway, you just put like a key, like you want zero, you just add a key of zero. That's technically how arrays still work. Yeah. So yeah, ([Time 0:42:40](https://share.snipd.com/snip/4a6bed81-0839-454f-a4f9-f212e431b1f2)) - **Treat AI As A Capability Multiplier** - Use AI as an augmenting tool to expand what you can learn and build, not as a replacement for developing deeper skills. - Dimitri sees AI as a capability enhancer that opens paths to learn new languages and problems when used intentionally. Transcript: Wes Bos You seem to love learning and getting into the weeds. I'm curious if you have any thoughts on people who are just using AI to poop out all of their code right now and not continuing their skill set into learning more things? Dimitri Metropolis I'm good with it. I think, yeah, I think this industry has grown so much in the last 10 years. And I think that most of us who have been doing it for a couple of years have worked with someone and you've had the thought about them that like, do you really love this? Or you just did this because somebody told you you would make a lot of money. Yeah. And I think that like, in the long term, I don't know if we need more software engineers than we have now. I think we need software engineers to be more capable. We need more like, so I look at AI as a capability enhancer. It allows me to do things like Type Slayer has a problem with, I don't know, it doesn't work with glibc version 2.39 and below because there's some Linux thing. I deeply do not care about learning. Yeah, right. Yeah. Yeah. I really don't want to do that. And I'm not someone like as evidenced by the doom thing. Like I will take the time to learn things if the situation arises. It's not like that. But I think that sometimes we don't have the power to pick and choose. And I also like that it gives you a chance to learn things that are outside of your range. Like you can, if you want to learn a new language, but you don't know somebody who knows that language. How do you, even like human natural languages, right? It's the same way. Like if you don't have someone to speak with, it's going to be really tough. You know, it's only so much fun with Duolingo in the closet, right? ([Time 0:45:13](https://share.snipd.com/snip/a747495c-35bd-43af-b161-76268abb9d36))