Prologue
Meet the Cast
The Experts
Prof. Eli Typeworth
Language Theorist
The whiteboard in Eli’s office has been erased and rewritten so many times that the ghost of a lambda calculus proof is permanently etched into the surface. He doesn’t mind. He says it reminds him that every type system is built on the shoulders of ideas older than computers themselves.
Eli wants to know which claim everyone is arguing about. In a review of an event system, he asked the team to set aside the class diagram and write down what had to remain true when an event arrived twice. They discovered they disagreed about that too. Guy stayed at the board with him; Oded went to find the retry code.
His smaller examples make a problem easier to reason about, but he can remove a requirement along with the distracting detail. Eden keeps asking him to put the old client back into the example. Eli usually wants another minute to finish the argument first. His patience is easier to appreciate when you aren’t waiting to merge.
“Let us return to first principles.”
Daniel Compiler
Compiler Internist
Daniel has read the TypeScript compiler source code the way some people read novels — for pleasure, on weekends. He once found a bug in the type checker during a code review because the behavior “felt wrong” to him. He was right.
Daniel tends to open a playground while someone is still explaining the problem. He wants a small example, the compiler version, and the diagnostic. When the result contradicts a claim, he’ll turn his laptop around: “The compiler disagrees.” When it doesn’t, he keeps the example open and asks what else was in the original file.
His humor is dry enough to start fires. When Oded once argued that a particular as assertion was “perfectly safe in practice,” Daniel responded: “The Titanic was perfectly safe in practice. Until the iceberg.”
Reducing a problem is also where he can lose it. A missing project flag or declaration file can make his tidy reproduction answer a different question. Eden has learned to bring the repository configuration along with the snippet. And a compiling example rarely satisfies Noam until someone has called the function.
“The compiler disagrees.”
Gilad Stacktrace
Systems Architect
Gilad Stacktrace has been building production systems since before TypeScript existed. Before Node.js existed. Before some of the professionals in this book were born. He has the calm demeanor of someone who has seen every architectural trend arrive as a revolution and settle as a footnote.
He doesn’t speak in abstractions. When someone proposes a pattern, Gilad asks one question: “Show me the stack trace.” Not metaphorically — he literally wants to see what happens at 3 AM when this pattern hits an edge case and the on-call engineer is staring at logs. If you can’t trace from the error to the root cause in under a minute, Gilad considers the pattern a failure, no matter how elegant it is.
Gilad often recognizes an old incident in a new proposal. This is useful until he starts bringing the old system’s precautions along with it. He once wanted retry handling and a recovery queue for an import tool that could simply be rerun. Oded asked who would maintain the queue. They kept the error report and dropped the queue; Gilad still wanted to know who would read the report.
His code reviews are legendary. Sparse, precise, and occasionally devastating. His most common comment: “This works. What happens when it doesn’t?”
“Show me the stack trace.”
Liron Closure
FP & Design Master
Liron started programming in Lisp in the early nineties, moved to Clojure when it emerged, and watched the functional programming wave hit the mainstream with the quiet satisfaction of someone who’s been saying the same thing for three decades. He’s not smug about it — he’s too warm for that — but he does have a habit of starting stories with “In Clojure, we solved this in 2009...”
He speaks in parables. When the team was debating whether to use mutable state in a performance-critical module, Liron told a story about a river. “A river looks like it’s staying still, but it’s always moving. Your mutable object looks like it’s staying the same, but every function that touches it might change it. The river is honest about what it is. Your object is not.” Noam immediately printed the quote and pinned it above his desk.
Liron likes finding a familiar pattern inside an unfamiliar problem. In a conversation about error handling, he’ll reach for something the team already knows about null propagation or asynchronous work. Dafna follows him quickly. Guy usually asks what happens to the connection they still have to close. That is where Liron has to leave the analogy and work through the code.
He is less patient with an abstraction that nobody can explain than with a page of repetitive code. “Complexity is a choice, not a necessity,” he says. Linoy has asked him whether the abstraction was hard to explain or whether he had interrupted the explanation. They still disagree about that helper.
“Complexity is a choice, not a necessity.”
Sahar Firstclass
Simplicity Expert
Sahar often says little while the others compare implementations. He is looking at the caller, trying to work out whether the proposed abstraction needs to exist. When he finds a use for it, he wants that use in the example. When he can’t, he asks what would happen if they removed it.
He came to TypeScript from Scheme. Before that, from a decade of writing code that other people had to maintain after he left — embedded systems where a careless abstraction cost real money, and small teams where every additional concept in the codebase had to be paid for in onboarding weeks. This shaped him. He does not believe in cleverness. He believes in removal — that the best code is the code you found a way not to write, and the second-best is the code anyone on the team can read without a glossary.
He and Liron often end up on the same side of a review, though they can irritate each other getting there. Liron wants the team to recognize a pattern they can reuse. Sahar wants to see whether this caller needs it at all. Liron has accused him of solving the example and leaving the library author to deal with everything else.
Sahar can underestimate how much work a familiar convention saves the people using it. Guy keeps bringing him reviews and incident logs from the team that would have to adopt his replacement. Sahar still asks whether the feature earns its place, but the cost of removing it belongs in the answer.
“Simple made better.”
The Professionals
Noam Kiperman
Type Safety Absolutist
It’s 11:47 PM on a Tuesday, and Noam is still reviewing pull requests. He has left forty-seven comments on a single PR. Forty-three of them are about type safety. The other four are about naming conventions, which he considers a form of type safety.
Noam treats any the way a health inspector treats an open sewer — with alarm, documentation, and an immediate remediation plan. He once blocked a deployment for six hours because he found a single as any buried in a utility function. When Oded argued it was “fine, it’s just a helper,” Noam pulled up the git log and showed three production bugs in the last year that traced back to “just a helper” type assertions.
He’s not unreasonable — he’s just relentless. He genuinely believes that most runtime errors are type errors in disguise, and he has the receipts to prove it. His Slack status permanently reads: “Your any is my on-call page.”
When he gets passionate in a debate, which is often, he’ll push his glasses up, lean forward, and say something like: “Over my dead type definition.”
People joke about Noam, but they also notice that his team’s error rates are the lowest in the company.
“Over my dead type definition.”
Oded Shipley
Velocity Advocate
Oded has deployed to production on a Friday. Twice. This month.
He’s not reckless — he just has a fundamentally different risk calculus than Noam. Where Noam sees a potential runtime error, Oded sees a feature that’s not shipping. Where Noam sees as any as a liability, Oded sees it as a bridge to getting the PR merged before standup.
His desk has a sticky note that says “Perfect is the enemy of shipped.” Below it, in smaller writing: “Also, good is the enemy of shipped.” He once rewrote an entire team’s contribution guide to add the sentence: “If your PR has been open for more than 48 hours, the types are too strict.”
Oded isn’t stupid — he graduated top of his class and can write sophisticated generic types when he wants to. He just believes that type safety has diminishing returns and that most teams over-invest in compile-time guarantees at the expense of features, feedback, and iteration speed.
His debates with Noam are the stuff of company legend. They once argued about optional chaining versus explicit null checks for forty-five minutes in a design review. The project they were reviewing launched three months late. Oded still brings this up.
“We can fix it in the next sprint.”
Gil Benchmark
Data-Driven Analyst
Gil doesn’t have opinions. Gil has datasets.
When a debate starts, Gil opens his laptop. While everyone else argues from experience and intuition, he’s querying production error logs, measuring bundle sizes, counting type assertion usage across the codebase, and pulling up adoption metrics from industry surveys.
In one review, he asks how many errors a change prevented. In another, he asks whether the two teams counted the same kind of error. He has ended meetings by discovering that the available data could not answer the question everyone was arguing about. Oded considers that an expensive way to reach lunch. Gil considers it useful.
Gil is suspicious of anecdotes, allergic to “in my experience,” and physically uncomfortable when someone says “everyone knows that.” He considers unsubstantiated claims a form of technical debt.
He keeps a running spreadsheet he calls “Things People Asserted That Turned Out To Be Wrong.” It has 847 entries.
“What does the data say?”
Eden Legacy
Migration Veteran
Eden has migrated three million lines of JavaScript to TypeScript. Not in a hackathon. Not as a proof of concept. In production, with real users, over eighteen months, while the team continued shipping features.
He has stories. The time a seemingly safe type change broke an API contract with a mobile app from 2019 that nobody knew still existed. The time a strict: true migration revealed that 40% of the codebase’s error handling was effectively dead code. The time an intern added @ts-ignore to “fix” a type error and accidentally silenced a warning about a null pointer that brought down the billing system.
Eden’s perspective is unique because he’s seen every pattern succeed and fail at scale. He’s not ideological — he’s empirical. When Noam argues for strict types, Eden agrees in principle but adds: “I’ve seen this fail at scale” — and then describes exactly how. When Oded argues for pragmatism, Eden agrees in principle but adds: “I’ve seen this fail at scale too” — and describes how.
He’s the one who always asks: “What’s the migration path?” If a pattern doesn’t have an incremental adoption story, Eden considers it academic.
“I’ve seen this fail at scale.”
Linoy Nightly
Cutting-Edge Advocate
Linoy’s tsconfig.json looks like a dare she has already taken. She reads TypeScript release notes the day they’re published. By lunch, she’s usually found a place to try the feature. By three, Oded has asked whether that place had a problem before lunch.
She likes code that lets the compiler do more of the work: satisfies for a configuration, inferred keys at a call, a type derived from the value everyone already maintains. When someone asks “can TypeScript do that?”, she usually has a playground open before they’ve finished the question. If it can’t, she may have a proposal ready. A proposal is not a shipped feature, a distinction Daniel has had to make while she was already typing.
Her enthusiasm gets ahead of the implementation sometimes. A signature fits the caller beautifully, and she wants everyone to see it; Noam wants to see what the body can get wrong. She’ll run his broken example. She’ll also try to repair hers before giving it up.
She’s had PRs rejected because the reviewer’s editor didn’t support the syntax yet. She now brings the compiler version with the example. The reviewer still has to read it, which is where her arguments with Oded tend to begin.
“There’s an RFC for that.”
Chen Override
Socratic Skeptic
Chen doesn’t propose solutions. Chen asks questions.
In a design review, Chen will sit silently for the first twenty minutes. Arms crossed. Listening. Then, when the room is converging on an approach, Chen will unfold his arms, lean forward, and say: “But have you considered...” — followed by a question so precisely targeted that the entire discussion unravels.
It’s infuriating. It’s also indispensable.
Chen once derailed a month of architecture planning with a single question: “What happens when two users edit the same document at the same time?” The team had designed an entire real-time collaboration system without considering concurrent edits. Chen didn’t suggest a solution — he never does — he just kept asking questions until the team realized they needed to start over.
Nobody wants Chen in their design review. Everyone needs Chen in their design review. The team has a saying: “If Chen can’t break it, ship it.”
Chen’s contribution to debates isn’t a position — it’s pressure-testing everyone else’s position. He finds the cracks. What you do with that information is your problem.
“But have you considered...”
Dafna Functor
FP Purist
Dafna writes TypeScript like it’s Haskell with better marketing.
Every function is pure. Every data transformation is a pipeline. Every piece of state is immutable. When Dafna looks at a for loop, she sees a reduce that lost its way. When Dafna sees a class, she sees a closure that’s been over-accessorized. When someone mutates an array in place, Dafna reacts like she’s witnessed a small crime.
Dafna’s code is beautiful. Genuinely beautiful. Her pipelines read like prose — users.filter(isActive).map(toProfile).reduce(groupByDepartment, {}). Clean, declarative, each step doing exactly one thing. The problem is that not everyone can read the prose. Oded once stared at one of Dafna’s compose chains for ten minutes and said: “I have no idea what this does, but I’m sure it’s elegant.”
Dafna and Guy are natural foils. Where Guy sees a well-structured class with clear responsibilities, Dafna sees unnecessary ceremony. Where Dafna sees a clean pipeline, Guy sees “where is the encapsulation?” Their arguments are the book’s recurring main event.
Dafna keeps examples of bugs caused by shared mutable state. She can show which function changed an object and which caller expected the old value. Guy usually asks how the object acquired so many owners. They can spend a meeting agreeing about the bug and disagreeing about what would have prevented it.
“That’s just a map.”
Guy Singleton
OOP Advocate
Guy has a whiteboard in his office. On it, at all times, is a class diagram. The classes have clear responsibilities, well-defined interfaces, and proper encapsulation. Guy considers this whiteboard a form of documentation, communication, and art.
He came up through Java and C#, where the Gang of Four design patterns weren’t suggestions — they were load-bearing architecture. He moved to TypeScript because he saw a language that could finally bring proper object-oriented design to the frontend. When he sees a class keyword in TypeScript, he feels at home.
Guy’s arguments are strong because they come from a place of real success. He’s built systems with class hierarchies that have survived five years of feature additions without major refactors. He’s seen the Strategy pattern eliminate a 2,000-line switch statement. He’s watched the Observer pattern cleanly separate concerns in ways that Dafna’s event-driven pipelines couldn’t match.
When Dafna proposes a functional solution, Guy’s first question is always: “Where’s the interface?” — meaning, where’s the contract? Where’s the boundary? How does the next developer know what this thing expects and what it guarantees? He considers Dafna’s compose chains “implicit contracts” and he doesn’t trust implicit anything.
Guy is at his best when he’s pushed. When Dafna or Noam corner him with a case where OOP patterns genuinely fail, he doesn’t retreat — he adapts. He’s the one who finds the object-oriented solution that addresses the functional critique, or who honestly admits when a class isn’t the right tool. That honesty makes his arguments more credible, not less.
“Where’s the interface?”
Dima Bridge
Balanced Pragmatist
Dima is the person both sides of an argument quote when they think they’re winning. This is because Dima has said validating things about both sides, and both sides only remember the validation.
He came to programming through a winding path — started in data science, moved to backend development, spent two years doing frontend, then ended up as a tech lead responsible for full-stack architecture. This breadth gives him a perspective that specialists lack: he’s seen FP patterns shine on the backend and struggle on the frontend. He’s seen OOP patterns create clean UI architectures and nightmarish backend god-objects. He’s used any when it was the right call and strict: true when it was the right call.
Dima’s first move is to find out whether both sides are answering the same question. Noam wants to know what a generic preserves; Oded wants to know why this function needs one today. Dima can agree with both without pretending they’ve reached a decision. “Both have a point here” is usually followed by someone discovering that their point doesn’t settle the other person’s problem.
Then he gets specific. Which caller needs the new entry point? Who owns the calculation? What input are they agreeing to accept? He’ll keep two interfaces when they serve two callers, and refuse a second implementation of the same rule. Both sides can have a point. One of them still has to change the code.
Noam has accused him of “centrist type theory.” Oded calls him “the human ‘it depends.’” Dima considers both descriptions complimentary, though Oded likes the answer less when Dima is the one making the call.
“Both have a point here.”
Idan Greenfield
Parse-Don’t-Validate Advocate
Idan came to TypeScript through schemas. Her formative years were spent building services that consumed APIs nobody owned and storing data on disks nobody had documented — the kind of work where the bug is never what the code does, it’s always what arrived through the door. She read Alexis King’s “Parse, Don’t Validate” early and never quite got over it. Her copy of the essay has marginalia, which is unusual, because it’s a blog post.
She prefers a parser that builds the value it promises. If a developer adds a required field to the type, she wants the return object to fail compilation until that field is produced. An explicitly annotated predicate can omit the new check and keep compiling. She has reviewed that mistake too often to be reassured by a function named isUser.
She’s distinct from Dafna, despite the surface FP overlap. Dafna lives inside the pipeline — purity, immutability, declarative composition over the whole program. Idan lives at the door. Once data is parsed and shaped, she defers to Dafna entirely; she has no opinions about your reduce. But she will spend a remarkable amount of energy on the thirty lines where bytes from the network become a typed value, because that’s where every production bug she has ever seen actually lived.
Her debates with Guy often concern where failure goes. Guy wants a request handler to catch a validation error once and end the operation. Idan wants the return type to tell each caller that the input may be rejected. They can agree on the parser and its checks and still argue about the function that calls it. Guy has existing handlers to maintain. Idan keeps finding callers outside them.
She’s not a moralist. She doesn’t lecture. She has, over time, become the engineer who has seen the same shape of production bug enough times that she stopped explaining it and started building around it.
“Prove it by producing it.”
The Cast at a Glance
Experts
| Name | Role | In One Line |
|---|---|---|
| Prof. Eli Typeworth | Language Theorist | Wants the claim stated precisely enough to test |
| Daniel Compiler | Compiler Internist | Opens the playground; asks which compiler you used |
| Gilad Stacktrace | Systems Architect | Doesn’t care if it’s elegant — does it survive 3 AM? |
| Liron Closure | FP & Design Master | Has been saying the same thing since Clojure in 2009 |
| Sahar Firstclass | Simplicity Expert | Checks the caller before adding the abstraction |
Professionals
| Name | Role | In One Line |
|---|---|---|
| Noam Kiperman | Type Safety Absolutist |
Your any is his on-call page |
| Oded Shipley | Velocity Advocate | Has deployed to production on a Friday. Twice. This month. |
| Gil Benchmark | Data-Driven Analyst | Doesn’t have opinions. Has datasets. |
| Eden Legacy | Migration Veteran | Has migrated three million lines and lived to tell about it |
| Linoy Nightly | Cutting-Edge Advocate | Brings a new feature, then tries it on your caller |
| Chen Override | Socratic Skeptic | If Chen can’t break it, ship it |
| Dafna Functor | FP Purist |
Sees a for loop, mourns a reduce |
| Guy Singleton | OOP Advocate | Considers his whiteboard class diagram a form of art |
| Dima Bridge | Balanced Pragmatist | Separates the questions, then makes the call |
| Idan Greenfield | Parse-Don’t-Validate | Wants to see the value the parser actually produced |
Now that you’ve met the cast, let’s see them in action.