After this lesson, you will be able to: Apply mapped types, conditional types, template literal types, infer, and the utility types.
Advanced TS. Used by library authors; senior application devs should recognise + occasionally write.
Built-in. Memorise these.
type User = { id: string; name: string; email: string; admin: boolean };type PartialUser = Partial<User>; // all fields optionaltype RequiredUser = Required<User>; // all fields requiredtype ReadonlyUser = Readonly<User>;type Pub = Omit<User, "admin">;type Min = Pick<User, "id" | "name">;type Map = Record<"admin" | "member", User>;type UserKeys = keyof User;type IdType = User["id"];// Function-relatedfunction fetch(id: string, opts?: { cache: boolean }): Promise<User> { return null as any; }type Args = Parameters<typeof fetch>; // [string, opts?: ...]type Ret = ReturnType<typeof fetch>; // Promise<User>type Resolved = Awaited<Ret>; // User// String typestype NonEmpty<T extends string> = T extends "" ? never : T;type Upper = Uppercase<"hello">; // "HELLO"
Transform keys of an object type.
type Nullable<T> = { [K in keyof T]: T[K] | null };type NullableUser = Nullable<User>;// Pick from another typetype Keys<T> = { [K in keyof T]-?: K }[keyof T]; // -? makes required// Add prefix to keys (template literal magic)type Prefixed<T, P extends string> = {[K in keyof T as `${P}${string & K}`]: T[K];};type DBUser = Prefixed<User, "db_">;// { db_id: string; db_name: string; db_email: string; db_admin: boolean }
Type-level if/else.
type IsArray<T> = T extends any[] ? true : false;type A = IsArray<number[]>; // truetype B = IsArray<number>; // false// Extract type from a generictype ElementOf<T> = T extends (infer U)[] ? U : never;type N = ElementOf<number[]>; // number// Extract the promise's resolved typetype Unwrap<T> = T extends Promise<infer U> ? U : T;type X = Unwrap<Promise<string>>; // stringtype Y = Unwrap<number>; // number// Template literal typetype Event = `on${"Click" | "Hover" | "Focus"}`;// "onClick" | "onHover" | "onFocus"
Reaching for advanced types when simple ones work. Over-engineering hurts readability. Recursive mapped types that hit the depth limit. Linear is fine; trees rarely. Forgetting `as const` on tuples. Without it, TS widens to plain arrays. Casting with `as Type` instead of fixing the underlying type.
Pick the cleanest answer.
Sign in and purchase access to unlock this lesson.