Skip to content

Advanced Type Tools

Advanced type tools in TypeScript help you create types that are more powerful and reusable. In this section, we will learn about utility types, mapped types, conditional types, and the keyof, typeof, and infer keywords. By the end of this section, you will understand how to use these advanced type features to write cleaner and easier-to-maintain TypeScript code.

These are ready-made helpers built into TypeScript that handle common type changes for you, so you do not need to write them yourself.

interface User {
id: number;
name: string;
email?: string;
}
type UserPatch = Partial<User>;
type FullUser = Required<User>;
type UserPreview = Pick<User, "id" | "name">;
type UserWithoutEmail = Omit<User, "email">;
type UserMap = Record<string, User>;

Here is what each one does in simple words: Partial makes every property optional, Required makes every property required, Pick lets you choose only some properties, Omit lets you remove some properties, and Record lets you create an object type with a chosen key type and value type.

Mapped types let you build a new type by going through each key of an existing type, one by one.

type ReadonlyUser<T> = {
readonly [K in keyof T]: T[K];
};
type ImmutableUser = ReadonlyUser<User>;

This example takes every property of T and makes it readonly, which means it cannot be changed after it is set.

Conditional types work like an if/else statement, but for types instead of values.

type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // true
type B = IsString<123>; // false

In simple words, this checks: “does T match a string? If yes, the result is true, if no, the result is false.”

const config = {
apiUrl: "https://example.com",
timeout: 5000,
};
type Config = typeof config;
type ConfigKeys = keyof Config; // "apiUrl" | "timeout"
  • typeof (when used in a type, not in normal code) takes a value and creates a type out of it.
  • keyof takes a type and gives you a union of all its property names.

infer is a special keyword that lets TypeScript pull out (or “guess”) a type from inside another type, while it is checking a condition.

type ReturnTypeOf<T> = T extends (...args: never[]) => infer R ? R : never;
type Fn = (x: number) => string;
type Result = ReturnTypeOf<Fn>; // string

In simple words, this example looks at a function type and pulls out its return type. So here, Result becomes string, because that is what Fn returns.

graph TD A[Source Type] --> B[Utility Type] A --> C[Mapped Type] A --> D[Conditional Type] D --> E[infer Extract] A --> F[keyof and typeof]