Union and Intersection Types
Combining multiple types using OR (|) and AND (&) operations.
🧑🏫 Sabse pehle — simple mein samjho#
Programming mein kai baar ek variable sir ek hi type ka nahi hota. Kabhi ID number ho sakti hai, kabhi string. TS mein types ko aapas mein merge (combine) karne ke do tareeqe hain: Union (Ye YA Phir Wo) aur Intersection (Ye AUR Wo dono).
Union Types (| - OR)#
A Union implies "one of these types". You use the | (pipe) operator to create one. This is heavily used in React for state and props.
function printId(id: number | string) {
// At this point, TS doesn't know if 'id' is a number or string.
// Therefore, only methods common to both types are allowed.
console.log("Your ID is: " + id);
// If you want to use a specific string method, you must check the type first (Type Narrowing).
if (typeof id === "string") {
console.log(id.toUpperCase());
}
}
printId(101); // ✅
printId("202-A"); // ✅
// printId(true); // ❌ ERROR: boolean is not string or number
Union in Arrays#
If you want an array to hold different types of values:
let mixedArray: (number | string)[] = [1, "two", 3];
Intersection Types (& - AND)#
Intersection means "combining multiple types to create a single, larger type". It acts much like merging two objects together. This is mostly used with type aliases.
type Person = {
name: string;
};
type Employee = {
employeeId: number;
};
// Intersection!
type Worker = Person & Employee;
const myWorker: Worker = {
name: "Tarun",
employeeId: 444
};
// Both properties must be provided. Missing even one will result in an error.
Note: What extends does for Interfaces, the & operator does for Types.
Discriminated Unions (The Ultimate Pattern 🏆)#
This pattern is extremely popular in Redux reducers or React's useReducer. Here, we create a union of different object shapes, but we include a common property (a "discriminator") in all of them so TS can identify exactly which shape is currently active.
// 3 Different Types
interface Circle {
kind: "circle"; // This is the common "discriminator"
radius: number;
}
interface Square {
kind: "square";
sideLength: number;
}
// Creating a Union of them
type Shape = Circle | Square;
function getArea(shape: Shape) {
// At first, TS does not know what shape is.
// But as soon as we check the discriminator:
if (shape.kind === "circle") {
// TS now understands this is a Circle! It allows access to `.radius`.
return Math.PI * shape.radius ** 2;
} else {
// TS is smart enough to deduce that the only remaining option is a Square!
return shape.sideLength ** 2;
}
}
Discriminated Unions provide excellent type safety and robust autocomplete when used inside switch statements and if-else blocks!