March 5, 2021·5 min read·engineeringtypescriptdocumentationlearning

The new TypeScript Handbook makes compiler behavior part of the lesson

The rewritten TypeScript Handbook teaches concepts in dependency order and checks its examples with the compiler. That approach also exposes the distinction between static checking and emitted JavaScript.

Documentation examples can continue to look convincing after the compiler stops behaving as they describe. A language guide needs a way to detect that divergence, especially when it teaches inference and diagnostics. The rewritten TypeScript Handbook announced on March 5 makes compiler output part of the documentation workflow. Its code examples can show type information, errors and emitted files through the same machinery used to check them.

Orta Therox's announcement describes the rewritten Handbook as the website's primary learning resource after leaving beta. The project began in 2018, with constraints on both the teaching order and the examples. The result is a guided account of everyday TypeScript, with more exhaustive and specialized material assigned to reference pages.

I appreciate documentation that treats the language's behavior as something to demonstrate. TypeScript's ecosystem can produce impressive interfaces, but working effectively within it requires knowing which guarantees the compiler actually supplies. A guide that exposes those decisions is more useful than a catalogue of syntax alone.

Concepts have prerequisites

The announcement says the Handbook teaches incrementally, avoiding features that have not yet been explained. That constraint forces the authors to decide which concepts another explanation depends on. It also favors reading the guide in sequence, rather than treating every page as an independent reference entry.

The distinction matters for a language whose type expressions can refer to several other mechanisms. An example may be locally correct while remaining inaccessible because it assumes unfamiliar syntax or inference rules. Reordering the material can remove that obstacle without simplifying the feature into an inaccurate description.

The Handbook also assumes JavaScript knowledge instead of teaching JavaScript from the beginning. Separate introductory material addresses readers with different technical backgrounds. This establishes an audience boundary. The guide can spend its space on how TypeScript builds on JavaScript while directing other learning needs to appropriate resources.

That choice is useful for experienced engineers as well as newcomers to the language. It lets the guide explain where TypeScript adds a static interpretation to behavior the reader already knows. A reader can then distinguish a JavaScript runtime rule from a decision made by the checker.

The opening examples separate behavior from checking

The Handbook's opening chapter as published on launch day begins with the operations a value supports. A string can have a callable lowercase-conversion method while being noncallable itself. The same spelling of a variable therefore supports some operations and rejects others according to the value it holds.

The chapter uses that distinction to introduce static checking. The compiler can report that a known string is not callable before the program runs. This grounds the type discussion in a concrete operation, rather than beginning with a list of annotation forms.

It also explains failures that do not immediately throw at runtime. Accessing a missing property can produce undefined in JavaScript, while TypeScript can reject the property access statically. The type system is making a judgement about likely mistakes, not merely reproducing every operation that would raise an exception.

const profile = { name: "Ada" }

// The checker reports that this property does not exist.
profile.location

That example is deliberately small. It establishes that valid JavaScript execution and accepted TypeScript are different criteria. Once a reader understands the distinction, later explanations of object types and narrowing have a firmer basis.

Emission is another independent decision

The opening chapter also demonstrates that a type error does not necessarily stop JavaScript output. It describes noEmitOnError as the option that prevents emission when the checker reports errors. This is essential context for anyone treating a generated JavaScript file as evidence that checking succeeded.

The teaching sequence makes the motivation concrete through JavaScript migration. Existing code may run while still containing disagreements with the added static checker. Keeping emission possible supports incremental adoption. A project that requires checking to block output can choose the stricter option explicitly.

The chapter then introduces annotations and shows their removal from emitted JavaScript. An annotation does not install a runtime check on an argument. This fact limits what an application can infer about values arriving through unchecked boundaries, even when the source declaration describes them precisely.

function title(name: string): string {
  return name.toUpperCase()
}

The annotations describe what the checker expects. Their erasure means the runtime operation remains an ordinary method call. Understanding that separation early prevents later type examples from being mistaken for automatic validation of external input.

Examples are maintained with the compiler

The announcement describes examples with inline quick information and diagnostics, plus views of emitted .js and .d.ts files. When the website moves to a new compiler version, the Handbook's examples move with it. Changed results give contributors a concrete reason to examine the explanation.

The launch-day chapter shows the corresponding annotations in its documentation source. Examples declare expected error codes and request emitted output in relevant sections. These are instructions to the documentation tooling, so the guide can retain deliberately invalid examples without pretending they should compile successfully.

That is a useful maintenance distinction. A guide needs examples of errors to explain the checker, but a plain code fence cannot state mechanically which error is intended. Recording the expected diagnostic lets an author distinguish a teaching example from an accidentally broken snippet.

The opening chapter also uses type queries to expose inference without requiring a redundant annotation in the example itself. This allows the lesson to discuss what the compiler learned from an initializer while preserving the source that produced that inference.

I prefer this form of documentation because it gives examples an observable relationship to the implementation. The compiler cannot decide whether the surrounding explanation teaches well, but it can expose disagreement about the code's inferred types or reported errors. That leaves human review focused on claims the automated check cannot establish.

The rewritten Handbook also makes this information available outside a rich editor, including its downloadable formats. Its teaching method connects the source example to the checker and the emitted program. Readers can follow the distinction between those results from the early chapters, then carry it into the more involved types and library interfaces they encounter later in the guide.