You are viewing a free preview of this lesson.
Subscribe to unlock all 12 lessons in this course and every other course on LearningBro.
TypeScript's type system is remarkably expressive. Beyond basic types and generics, it provides mapped types, conditional types, the infer keyword, and a rich set of built-in utility types. These advanced features allow you to create types that transform other types, enforce complex constraints, and eliminate boilerplate.
Mapped types create new types by transforming each property of an existing type:
// Make all properties optional
type MyPartial<T> = {
[K in keyof T]?: T[K];
};
// Make all properties readonly
type MyReadonly<T> = {
readonly [K in keyof T]: T[K];
};
// Make all properties nullable
type Nullable<T> = {
[K in keyof T]: T[K] | null;
};
interface User {
id: number;
name: string;
email: string;
}
type PartialUser = MyPartial<User>;
// { id?: number; name?: string; email?: string }
type ReadonlyUser = MyReadonly<User>;
// { readonly id: number; readonly name: string; readonly email: string }
You can remap keys in mapped types using the as clause:
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
type UserGetters = Getters<User>;
// { getId: () => number; getName: () => string; getEmail: () => string }
Conditional types select one of two types based on a condition, using the extends keyword:
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
type C = IsString<'hello'>; // true
When a conditional type is applied to a union, it distributes over each member:
type ToArray<T> = T extends unknown ? T[] : never;
type Result = ToArray<string | number>;
// string[] | number[] (not (string | number)[])
The infer keyword allows you to extract a type from within a conditional type:
// Extract the return type of a function
type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type Fn = (x: number, y: number) => string;
type FnReturn = MyReturnType<Fn>; // string
// Extract the element type from an array
type ElementType<T> = T extends (infer E)[] ? E : never;
type NumElement = ElementType<number[]>; // number
type StrElement = ElementType<string[]>; // string
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
Subscribe to continue reading
Get full access to this lesson and all 12 lessons in this course.