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.

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!