Type-Level Programming

Preview — 3 of 10 questions

Why doesn't this code catch the bug at compile time without branded types?

javascript
type UserId = string;
type ProductId = string;

function getUser(id: UserId) { /* ... */ }
const productId: ProductId = "prod_123";
getUser(productId); // ← bug: wrong ID type, but no error!
ATypeScript never checks function argument types
BTypeScript only checks primitive types in strict mode
Cstring extends UserId, so the assignment is valid
DUserId and ProductId are structurally identical — both are just string, so TypeScript sees them as the same type

What is the advantage of satisfies over a direct type annotation?

javascript
const palette = {
  red: [255, 0, 0],
  green: "#00ff00",
  blue: [0, 0, 255],
} satisfies Record<string, string | number[]>;
Asatisfies makes the type mutable at runtime
Bsatisfies validates the type at compile time but preserves the narrowest inferred type for each property — palette.red is number[], not string | number[]
Csatisfies is identical to as — it bypasses type checking
Dsatisfies makes all properties readonly

Which assignment is valid in TypeScript's structural type system?

javascript
type Animal = { name: string };
type Dog    = { name: string; breed: string };

let animal: Animal;
let dog: Dog = { name: "Rex", breed: "Lab" };
ABoth assignments are valid
Bdog = animal ✅ — Animal is more general, so it covers Dog
Canimal = dog ✅ — Dog has all Animal properties (covariance for object types)
DNeither assignment is valid

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.