TypeScript Survival Guide

Favorite typescript videos

060 — Learn Advanced TypeScript In 25 Minutes (infer, extends, ternaries)

The video climbs four rungs: `extends` means *superset* in every context — `Dog extends Animal`, `interface B extends A`, `T extends string` as a generic constraint ("at least a string"), and `T extends string ? true : false` as a compile-time `if`. `infer` adds extraction: `T extends unknown[] ? infer A` captures the element type into a new variable, which rebuilds `ReturnType` and `Awaited` from

Video: 060 · Learn Advanced TypeScript In 25 Minutes (infer, extends, ternaries) · watch · ~25:54 · Web Dev Simplified

Source: this is a written companion to the video. Part of the Favorite TypeScript Videos curated path.

The video climbs four rungs: extends means superset in every context — Dog extends Animal, interface B extends A, T extends string as a generic constraint (“at least a string”), and T extends string ? true : false as a compile-time if. infer adds extraction: T extends unknown[] ? infer A captures the element type into a new variable, which rebuilds ReturnType and Awaited from scratch. Template-literal patterns (${infer K}:${infer V}, `{${infer Param}}`) parse strings into types — the engine behind an i18n extractParams type. Finally in keyof T loops over object keys to transform values, toggle readonly/? with +/- modifiers, and rename keys with as (a getName/getAge getter-type demo). Recurring warning: nested conditional ternaries are the only if TypeScript types get, so real-world types read as deep ternary chains.

extends as superset — classes, interfaces, and & for type aliases

Dog extends Animal means Dog contains everything an animal has, plus more. For interfaces, B extends A makes B a superset of A — everything in A plus potentially more — extendable to multiple parents (B extends A, C). Type aliases cannot use extends; instead the & symbol combines them. The corrective refrain: extends does not mean “and” — it means superset.

Generic constraints — T extends string means “at least a string”

type Generic<T extends string> = { name: T };

T is a superset of string: a string, or a string plus more — a custom string-with-age type passes, while number errors because it does not satisfy the constraint. The use is narrowing: demanding that a generic be a string, an object, or a function.

Conditional types — ternaries are the only if

type IsString<T> = T extends string ? true : false;

Is T at least as big as string? If so, take the branch after the ? — a normal ternary — otherwise take the branch after the :. Applied to properties (value: T extends string ? string : number) and nested for number/undefined fallbacks. There is no other if at the type level, so real-world types often read as deep chains of nested ternaries.

infer — capturing types inside a match

type ElementOf<T> = T extends (infer A)[] ? A : never;
type CustomReturnType<T> = T extends (...args: never[]) => infer R ? R : never;
type CustomAwaited<T> = T extends Promise<infer P> ? P : T;

Does T extend an array of any type? If so, capture the array’s element type into a new generic variable A — string[] yields string, non-arrays yield never — and inference chains further (A extends string ? number : never). The ReturnType rebuild constrains to (...args: never[]) => unknown, infers the return into R, and returns R — behaving identically to the built-in against fetch. The Awaited rebuild returns the unwrapped P, else T itself. infer is the most powerful tool for complicated types.

Template-literal patterns — parsing strings into types

type KeyValueSplitter<T extends string> = T extends `${infer K}:${infer V}`
	? { key: K; value: V }
	: never;

With name:Kyle the key is name and the value Kyle; a colon-less string falls to never. This same trio — extends + infer + template literals — powers the i18n extractParams type that pulls {param} placeholders out of translation strings.

Mapped types — looping over keys with in keyof T

type Mapped<T> = { [P in keyof T]: T[P] };
type Getters<T> = { [P in keyof T as `get${Capitalize<P & string>}`]: () => T[P] };

in keyof T visits every key of T — values redefinable per key, conditionals per value (extends string ? number : T[P]). Modifiers: -readonly removes readonly, bare readonly adds it, ? adds optionality, -? strips it. Renaming via as prefixes get + Capitalize<P>, constraining keys with Record<string, unknown> and P & string, then wrapping values in functions to build getters.

still from Learn Advanced TypeScript In 25 Minutes (infer, extends, ternaries)

Transcript corrections applied above: extends keyword (not extends keyboard); param type (not peram type); ternaries (not ternnaries / terrares); getters (not gitters); in keyof (not this in Kiev); S extends string (not S extends its string); extractParams-style i18n options type (not extractR options).

Prev: 059 — You are a Junior Dev if You Don’t Know These 18 TypeScript Utility Types · Next: 061 — This Amazing TypeScript Feature Has NO Docs!