5 exercises on advanced TypeScript terms — the type system in depth.
0 / 5 completed
1 / 5
What are generics in TypeScript?
Generics let you write reusable functions, classes, and types that are parameterized over types rather than hard-coding a specific one. A generic like function identity<T>(x: T): T preserves the relationship between input and output, so the compiler knows the result type matches the argument — far safer than using any. You can constrain a type parameter (<T extends object>) to require certain capabilities, and often the compiler infers the type argument from usage. Generics are the foundation of TypeScript's type-safe abstractions like Array<T> and Promise<T>.
2 / 5
What is a conditional type?
A conditional type chooses one of two types based on a relationship between types, using the syntax T extends U ? X : Y — if T is assignable to U, the type resolves to X, otherwise Y. They enable powerful type-level logic and, combined with the infer keyword, let you extract pieces of a type (e.g. the return type of a function via ReturnType<T>). Conditional types distribute over union types when the checked type is a naked type parameter, applying the condition to each member. They power many of TypeScript's built-in utility types.
3 / 5
What is a mapped type?
A mapped type constructs a new type by iterating over the keys of an existing type and transforming each property, using the syntax { [K in keyof T]: ... }. You can change each property's type, and apply modifiers to add or remove readonly and optionality (e.g. -readonly, -?). Built-in utilities like Partial<T>, Required<T>, Readonly<T>, and Record<K, V> are all mapped types. Combined with key remapping via as, they let you rename or filter keys, enabling rich type transformations without repetition.
4 / 5
What is type narrowing?
Type narrowing is the process by which TypeScript refines a variable's type to something more specific within a particular branch of code, based on runtime checks the compiler can reason about. Constructs like typeof x === "string", Array.isArray(x), instanceof, truthiness checks, and equality comparisons act as type guards. After such a check, TypeScript treats the variable as the narrowed type inside that block. You can also write custom guards with a return type of x is T. Narrowing is what lets you safely work with union types.
5 / 5
What is a discriminated union?
A discriminated (tagged) union is a union of object types that each include a common literal property — the discriminant, such as kind: "circle" vs kind: "square". When you check that field (e.g. in a switch), TypeScript automatically narrows the value to the matching member, giving you type-safe access to that variant's specific properties. This pattern models "one of several shapes" cleanly and, paired with an exhaustiveness check using never, guarantees at compile time that every case is handled. It is the idiomatic way to represent state and result types.