7 Subtyping

 

In this chapter

  • Disambiguating types in TypeScript
  • Safe deserialization
  • Values for error cases
  • Type compatibility for sum types, collections, and functions

Now that we covered primitive types, composition, and function types, it’s time to look at another aspect of type systems: relationships between types. In this chapter we’ll introduce the subtyping relationship. While you might be familiar with it from object-oriented programming, we will not cover inheritance in this chapter. Instead, we will focus on a different set of applications of subtyping.

We’ll first talk about what subtyping is, and the two ways in which programming languages implement it: structural and nominal. We will then revisit our Mars Climate Orbiter example and explain the unique symbol trick we used in chapter 4, when discussing type safety.

Since a type can be a subtype of another type and it can also have other subtypes itself, we will look at this type hierarchy: we usually have a type which sits at the top of this hierarchy and, sometimes, a type which sits at the bottom. We’ll see how we can use this top type in a scenario like deserialization, where we don’t have a lot of typing information readily available. We’ll also see how we can use a bottom type as a value for error cases.

7.1       Distinguishing Between Similar Types in TypeScript

7.1.1 Structural and Nominal Subtyping Pros and Cons

7.1.2 Simulating Nominal Subtyping in TypeScript

7.1.3 Exercises

7.2       Assigning Anything to, Assigning to Anything

7.2.1 Safe Deserialization

7.2.2 Values for Error Cases

7.2.3 Top and Bottom Types Recap

7.2.4 Exercises

7.3       Allowed Substitutions

7.3.1 Subtyping and Sum Types

7.3.2 Subtyping and Collections

7.3.3 Subtyping and Function Return Types

7.3.4 Subtyping and Function Argument Types

7.3.5 Variance Recap

7.3.6 Exercises

7.4       Summary

7.5       Answers to Exercises

sitemap