TypeScript Utility and Conditional Types in 2025: Partial, Required, Pick, Omit, Exclude, ReturnType & Best Practices

1. What are utility types in TypeScript?

Q: Overview of built-in utility types and examples

Utility Types: Built-in TypeScript types that transform or manipulate other types to simplify type definitions.

What is the Partial<T> utility type?

Definition: Makes all properties of type T optional.

Can you give an example of Partial?


interface User { name: string; age: number; email: string;
} const updateUser = (user: User, updates: Partial<User>): User => ({ ...user, ...updates
}); const user: User = { name: "kristal", age: 30, email: "[email protected]" };
const updatedUser = updateUser(user, { age: 31, email: "[email protected]" });
console.log(updatedUser); 

Output:


{ "name": "kristal", "age": 31, "email": "[email protected]" } 

What is the Required<T> utility type?

Definition: Makes all properties of type T required, removing optional (?) modifiers.

Can you give an example of Required?


interface PartialUser { name?: string; age?: number;
} const enforceUser = (data: Required<PartialUser>): void => { console.log(`Name: ${data.name}, Age: ${data.age}`);
}; enforceUser({ name: "Sashi", age: 25 }); // Valid
// enforceUser({ name: "Sashi" }); // Error: Property 'age' is missing 

What is the Readonly<T> utility type?

Definition: Makes all properties of type T read-only (cannot be reassigned).

Can you give an example of Readonly?


interface Config { apiUrl: string; timeout: number;
} const config: Readonly<Config> = { apiUrl: "https://api.example.com", timeout: 5000
}; console.log(config.apiUrl);
// config.apiUrl = "new-url"; // Error: Cannot assign to 'apiUrl' because it is read-only 

What is the Record<K, T> utility type?

Definition: Creates an object type with keys of type K (string, number, or union) and values of type T.

Can you give an example of Record?


type Role = "admin" | "user" | "guest"; interface UserInfo { id: number; name: string;
} const users: Record<Role, UserInfo> = { admin: { id: 1, name: "kristal" }, user: { id: 2, name: "Sashi" }, guest: { id: 3, name: "hari" }
}; console.log(users.admin);
// users.admin = { id: 4 }; // Error: Property 'name' is missing 

Output:


{ "id": 1, "name": "kristal" } 

What is the Pick<T, K> utility type?

Definition: Creates a new type by selecting a subset of properties K from type T.

Can you give an example of Pick?


interface Employee { name: string; age: number; department: string;
} type BasicInfo = Pick<Employee, "name" | "age">; const employee: BasicInfo = { name: "kristal", age: 30 // department: "HR" // Error: 'department' is not allowed
}; console.log(employee); 

Output:


{ "name": "kristal", "age": 30 } 

What is the Omit<T, K> utility type?

Definition: Creates a new type by excluding properties K from type T.

Can you give an example of Omit?


interface User { id: number; name: string; password: string;
} type PublicUser = Omit<User, "password">; const publicUser: PublicUser = { id: 1, name: "Sashi" // password: "secret" // Error: 'password' is not allowed
}; console.log(publicUser); 

Output:


{ "id": 1, "name": "Sashi" } 

2. What are mapping and conditional types in TypeScript?

Q: Explanation of conditional types with examples

Mapping Types: Transform properties of an existing type using mapped types, often with the in keyword.

Conditional Types: Types that depend on a condition, using the T extends U ? X : Y syntax.

What is the Exclude<T, U> utility type?

Definition: Excludes types from T that are assignable to U.

Can you give an example of Exclude?


type Action = "create" | "update" | "delete" | "view";
type ReadOnlyAction = Exclude<Action, "create" | "update" | "delete">; const action: ReadOnlyAction = "view";
// const action: ReadOnlyAction = "create"; // Error: Type 'create' is not assignable
console.log(action); 

Output:


view 

What is the Extract<T, U> utility type?

Definition: Extracts types from T that are assignable to U.

Can you give an example of Extract?


type Action = "create" | "update" | "delete" | "view";
type WriteAction = Extract<Action, "create" | "update" | "delete">; const writeAction: WriteAction = "create";
// const writeAction: WriteAction = "view"; // Error: Type 'view' is not assignable
console.log(writeAction); 

Output:


create 

What is the NonNullable<T> utility type?

Definition: Removes null and undefined from type T.

Can you give an example of NonNullable?


type MaybeUser = { name: string } | null | undefined;
type User = NonNullable<MaybeUser>; const user: User = { name: "kristal" };
// const user: User = null; // Error: Type 'null' is not assignable
console.log(user.name); 

Output:


kristal 

What is the ReturnType<T> utility type?

Definition: Infers the return type of a function type T.

Can you give an example of ReturnType?


type FetchData = () => { id: number; name: string };
type Data = ReturnType<FetchData>; const data: Data = { id: 1, name: "Sashi" };
// const data: Data = { id: 1 }; // Error: Property 'name' is missing
console.log(data); 

Output:


{ "id": 1, "name": "Sashi" } 

3. Can you provide a comprehensive example combining utility and conditional types?

Q: Full demo with all major utility types

Project Structure:


ts-utility-types/
├── src/
│ └── main.ts
├── tsconfig.json
└── package.json 

main.ts:


// Comprehensive TypeScript example
interface Employee { id: number; name: string; department: string; salary?: number; role: "admin" | "user" | "guest" | null;
} // Utility Types
type PartialEmployee = Partial<Employee>;
type RequiredEmployee = Required<Employee>;
type ReadonlyEmployee = Readonly<Employee>;
type EmployeeRecord = Record<"manager" | "staff", Employee>;
type BasicEmployee = Pick<Employee, "id" | "name">;
type PublicEmployee = Omit<Employee, "salary">; // Conditional Types
type NonNullRole = NonNullable<Employee["role"]>;
type WriteRole = Extract<Employee["role"], "admin" | "user">;
type ReadOnlyRole = Exclude<Employee["role"], "admin" | "user">;
type GetEmployee = () => Employee;
type EmployeeData = ReturnType<GetEmployee>; // Example usage
const updateEmployee = (emp: Employee, updates: PartialEmployee): Employee => ({ ...emp, ...updates
}); const employee: Employee = { id: 1, name: "kristal", department: "IT", role: "admin" };
const updated: Employee = updateEmployee(employee, { salary: 60000 });
console.log("Updated Employee:", updated); const requiredEmp: RequiredEmployee = { id: 2, name: "Sashi", department: "HR", salary: 55000, role: "user"
};
console.log("Required Employee:", requiredEmp); const readonlyEmp: ReadonlyEmployee = { id: 3, name: "hari", department: "Sales", role: "guest" };
console.log("Readonly Employee:", readonlyEmp);
// readonlyEmp.name = "Dave"; // Error: Cannot assign to 'name' const empRecord: EmployeeRecord = { manager: { id: 4, name: "Dave", department: "IT", role: "admin" }, staff: { id: 5, name: "Eve", department: "HR", role: "user" }
};
console.log("Employee Record:", empRecord); const basicEmp: BasicEmployee = { id: 6, name: "Frank" };
console.log("Basic Employee:", basicEmp); const publicEmp: PublicEmployee = { id: 7, name: "Grace", department: "Marketing", role: "guest" };
console.log("Public Employee:", publicEmp); const role: NonNullRole = "admin";
// const role: NonNullRole = null; // Error: Type 'null' is not assignable
console.log("NonNull Role:", role); const writeRole: WriteRole = "admin";
console.log("Write Role:", writeRole); const readRole: ReadOnlyRole = "guest";
console.log("ReadOnly Role:", readRole); const fetchEmployee: GetEmployee = () => ({ id: 8, name: "Hank", department: "Finance", role: "user" });
const empData: EmployeeData = fetchEmployee();
console.log("Employee Data:", empData); 

package.json:


{ "name": "ts-utility-types", "version": "1.0.0", "scripts": { "start": "tsc && node dist/main.js", "build": "tsc", "watch": "tsc --watch" }, "devDependencies": { "typescript": "^5.6.2" }
} 

tsconfig.json:


{ "compilerOptions": { "target": "ESNext", "module": "ESNext", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true }, "include": ["src/**/*"], "exclude": ["node_modules"]
} 

Steps to Run:

  1. Create the project structure.
  2. Install dependencies: npm install.
  3. Compile: npm run build.
  4. Run: npm start.

Output:


Updated Employee: { "id": 1, "name": "kristal", "department": "IT", "role": "admin", "salary": 60000 }
Required Employee: { "id": 2, "name": "Sashi", "department": "HR", "salary": 55000, "role": "user" }
Readonly Employee: { "id": 3, "name": "hari", "department": "Sales", "role": "guest" }
Employee Record: { "manager": { "id": 4, "name": "Dave", "department": "IT", "role": "admin" }, "staff": { "id": 5, "name": "Eve", "department": "HR", "role": "user" } }
Basic Employee: { "id": 6, "name": "Frank" }
Public Employee: { "id": 7, "name": "Grace", "department": "Marketing", "role": "guest" }
NonNull Role: admin
Write Role: admin
ReadOnly Role: guest
Employee Data: { "id": 8, "name": "Hank", "department": "Finance", "role": "user" } 

Description:

4. What are common mistakes in using TypeScript utility and conditional types?

Q: Pitfalls to avoid

5. What are best practices for TypeScript utility and conditional types?

Q: Professional tips for 2025

  1. Utility Types:
    • Use Partial for optional updates; Required for strict validation.
    • Apply Readonly for immutable objects to prevent runtime errors.
    • Use Record for dynamic key-value mappings with type safety.
    • Combine Pick and Omit to create focused or sanitized interfaces.
  2. Conditional Types:
    • Use Exclude/Extract to filter union types precisely.
    • Apply NonNullable to ensure non-nullable values in critical paths.
    • Leverage ReturnType for function return type inference in APIs.
  3. General:
    • Keep type definitions DRY using utility types instead of redundant interfaces.
    • Use descriptive names for derived types (e.g., PublicUser instead of OmitUser).
    • Test types with edge cases (e.g., missing properties, null values).
    • Use TypeScript's strict mode (strict: true in tsconfig.json) for robust checks.
    • Document complex types with JSDoc or comments for clarity.