Someone forked TypeScript to add Go's defer keyword
A developer forked the TypeScript compiler to add Go-style defer statements. The implementation works, the maintenance burden is real.
Andrew Healey forked the TypeScript compiler to add Go’s defer keyword. The keyword pushes cleanup code onto a stack that runs when the function exits, regardless of how it exits.
The appeal is obvious. Instead of sprinkling finally blocks everywhere or remembering to close file handles in twelve different code paths, you write defer file.close() right after opening the file. The cleanup sits next to the allocation. Go developers swear by it.
Healey’s implementation compiles defer down to a try-finally block with a queue. When the function exits, the deferred calls run in reverse order. The actual compiler changes are surprisingly small: a new AST node, lexer token, parser logic, and some emit transforms. Most of the heavy lifting is reusing TypeScript’s existing exception-handling machinery.
The interesting bit is not whether it works. It does. The interesting bit is whether anyone would actually use a forked compiler for production code. TypeScript moves fast. The official compiler gets type system changes, performance fixes, and new language features every few months. A fork means rebasing forever or falling behind.
Python tried something similar with context managers. Java has try-with-resources. Rust has Drop traits. Every language solves the cleanup problem differently because cleanup semantics interact with the entire type system. Go’s defer works because Go has no exceptions, only explicit error returns. TypeScript has exceptions, async/await, and a type system that assumes the official compiler.
This reads as a learning exercise, not a proposal. Healey walks through the compiler internals and shares the diff. That is worth more than the feature itself. Forking a production compiler teaches you what the boundaries are.
I would not ship this to production. But I would read the implementation to understand how TypeScript’s emit phase works. The gap between “this compiles” and “this is maintainable” is the entire job.