Overview

1 Introduction to Typing

This chapter introduces typing as the discipline that gives meaning to raw bits, distinguishes code from data, and constrains what values are allowed where. It motivates types with real-world stakes (such as unit mismatches) and frames them as sets of possible values plus the valid operations on those values. A type system applies rules—either at compile time or at run time—to assign, infer, and enforce these types, converting many potential failures into early, actionable feedback. With this lens, types offer broad correctness guarantees, and the chapter briefly nods to the deep connection between types and logic, where well-typed programs embody proofs of desired properties.

The practical benefits center on five themes: correctness, immutability, encapsulation, composability, and readability. Correctness improves by shrinking the state space—rejecting invalid inputs and disallowing unsafe states before execution. Immutability preserves verified assumptions and curbs data races, while encapsulation prevents misuse by hiding representation behind safe interfaces. Composability emerges from generic, reusable building blocks that separate algorithms from data and reduce duplication. Readability rises as explicit types serve as precise, enforced documentation, with type inference reducing boilerplate without sacrificing clarity when used judiciously.

The chapter surveys the landscape of type systems: dynamic versus static (when checks occur) and weak versus strong (how many implicit conversions are permitted), using JavaScript and TypeScript to illustrate tradeoffs and pitfalls like surprising coercions. It clarifies how inference still operates at compile time and when explicit annotations are valuable. Finally, it sets expectations for the book’s pragmatic focus and audience, outlining the journey from primitive types and type composition through function types, subtyping, and generics, culminating in higher-kinded types—all aimed at helping practicing developers leverage modern static typing to build safer, more maintainable systems.

A sequence of bits can be interpreted in multiple ways
The sequence of bits typed as a signed 16-bit integer. The type information (16-bit signed integer) tells the compiler and/or runtime that the sequence of bits represents an integer value between -32768 and 32767, ensuring the correct interpretation as -15709.
Source code is transformed by a compiler or interpreter into code which can be executed by a runtime. The runtime is either a physical computer or a virtual machine, like Java’s JVM, or a browser’s JavaScript engine.
declaring a type correctly we can disallow invalid values: the first type is too loose and allows for values we don’t want (😈, 💀). The second, more restrictive type, won’t compile if the code tries to assign an unwanted value to a variable.

Summary

  • A type is a classification of data that defines the operations that can be done on that data, the meaning of the data, and the set of allowed values
  • A type system is a set of rules which assign and enforce types to elements of a programming language.
  • Types restrict the range of values a variable can take, so in some cases what would’ve been a run-time error becomes a compile-time error
  • Immutability is a property of the data enabled by typing, which ensures values don’t change when they’re not supposed to
  • Visibility is another type-level property which determines what components are allowed to access what data
  • Generic programming enables powerful decoupling and code reuse
  • Type notations make the code easier to understand for readers of the code
  • Dynamic typing or “duck typing” determines types at run-time
  • Static typing checks types at compile time, catching type errors which otherwise would’ve become run-time errors
  • The strength of a type system is a measure how many implicit conversions between types are allowed
  • Modern type checkers have powerful type inference algorithms which enables them to determine what are the types of variables, functions and so on without you having to explicitly write them out

In the next chapter we will look at primitive types, which are the building blocks of the type system. We’ll learn how to avoid some common mistakes that arise when using these types and see how we can build pretty much any data structure from arrays and references.

FAQ

Why do type systems exist, and what can go wrong without them?At the machine level, both code and data are just bits, so misinterpretation can cause crashes or security issues. In real projects, mixing incompatible values (like different measurement units) can be catastrophic. A type system prevents such mix-ups by encoding meaning and constraints so incompatible values can’t be combined.
What is a “type” and what is a “type system”?A type classifies data by its allowed values, the operations permitted on it, and its intended meaning. A type system is the set of rules that assigns and enforces types on program elements, either from explicit annotations or by inferring them, allowing safe conversions and rejecting unsafe ones.
What is type checking, and when does it happen?Type checking verifies that a program respects the rules of its type system. It can happen at compile time (static typing) or at run time (dynamic typing). If the rules are violated, you get either a compile-time error or a run-time error, respectively.
How do types give meaning to bits and restrict allowed values?Types tell the compiler/runtime how to interpret raw bits (for example, as a signed integer versus a character) and constrain what values are valid (e.g., a 16‑bit signed integer must be between −32768 and 32767). Viewing types as sets of possible values helps reason about correctness and avoid invalid states.
How do types improve correctness in practice?By adding precise types, you turn many potential run-time failures into compile-time errors. For example, a function that operates on strings will be rejected at compile time if you try to pass a number, preventing a run-time “method not found” crash.
Why is immutability valuable, and how do languages enforce it?Immutability keeps validated state from changing unexpectedly, which reduces bugs and eliminates data races in concurrent code. Languages enforce it via type-level qualifiers (e.g., const/readonly), and the compiler rejects attempts to mutate immutable values.
How does encapsulation relate to types?Encapsulation hides implementation details behind a public interface. Visibility modifiers (public/private) are type properties that the compiler enforces: code outside the boundary can’t access private members even though the underlying memory is the same, improving safety and modularity.
What is composability, and how do generics enable it?Composability is building general, reusable pieces that work across types and scenarios. Generics let you write algorithms like “find the first element matching a predicate” once (e.g., first<T>), then reuse them for numbers, strings, and beyond, reducing duplication and easing maintenance.
What’s the difference between static and dynamic typing?Static typing checks types at compile time, catching mismatches before code runs. Dynamic typing defers checks to run time, so type errors become run-time failures. TypeScript brings static typing to JavaScript, turning many potential run-time errors into compile-time ones.
What’s the difference between strong and weak typing?Strong typing minimizes implicit conversions and requires explicit casts, reducing surprises. Weak typing performs more implicit conversions (e.g., "42" == 42 is true in JavaScript), which can lead to unexpected results. TypeScript favors strong typing, so comparing incompatible types is rejected at compile time.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$399.99
only $33.33 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Programming with Types ebook for free
choose your plan

team

monthly
annual
$49.99
$399.99
only $33.33 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Programming with Types ebook for free