After this lesson, you will be able to: Apply advanced TypeScript: generics, utility types, mapped types, conditional types, declaration files.
This goes beyond the Web Dev TS intro. The advanced TypeScript content most JS devs never learn.
Functions that work for many types while preserving type info.
// Without generics, loses typefunction firstAny(arr: any[]): any { return arr[0]; }const x = firstAny([1, 2, 3]); // x: any ← bad// With generics, preserves typefunction first<T>(arr: T[]): T | undefined { return arr[0]; }const y = first([1, 2, 3]); // y: number | undefined// Generic constraintfunction longest<T extends { length: number }>(a: T, b: T): T {return a.length >= b.length ? a : b;}// Default type parametertype Result<T, E = Error> = { ok: true; data: T } | { ok: false; error: E };
The 10 you'll use weekly.
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 UserName = Pick<User, "id" | "name">; // subsettype UserPublic = Omit<User, "admin">; // excludetype RoleMap = Record<"admin" | "member", User>;type UserKeys = keyof User; // "id" | "name" | "email" | "admin"type IdType = User["id"]; // string// Function-relatedfunction fetchUser(id: string, opts?: { cache: boolean }): Promise<User> { /* ... */ }type FetchArgs = Parameters<typeof fetchUser>; // [id: string, opts?: { cache: boolean }]type FetchReturn = ReturnType<typeof fetchUser>; // Promise<User>type FetchAwaited = Awaited<FetchReturn>; // User
Advanced, most pros use these monthly.
// Mapped type, transform keystype Nullable<T> = { [K in keyof T]: T[K] | null };type NullableUser = Nullable<User>;// Conditional type, type-level if/elsetype IsArray<T> = T extends any[] ? true : false;type A = IsArray<number[]>; // truetype B = IsArray<number>; // false// infer, extract types from genericstype ElementOf<T> = T extends (infer U)[] ? U : never;type N = ElementOf<number[]>; // number// Template literal typestype Event = `on${"Click" | "Hover"}`; // "onClick" | "onHover"type HexColor = `#${string}`;
A .d.ts file describes types for code that has none (a JS library, a binary, an external API). DefinitelyTyped (`@types/foo`) hosts community-maintained types for popular libs. Writing your own: `declare module "untyped-lib" { export function fn(x: number): string; }`. Use sparingly; native TS libraries are increasingly the norm.
Using `any` to escape type problems. Almost always a code smell. Use `unknown` if you genuinely don't know. Reaching for advanced types when simple ones work. Don't over-engineer types. Skipping strict mode in tsconfig. Half the benefit comes from strict null checks. Casting with `as` instead of fixing the underlying type. Casts are escape hatches; use sparingly.
Pick the answer.
Sign in and purchase access to unlock this lesson.