๐ŸŽ“ A1Learner
๐Ÿ”
0 of 42 lessons completed

TypeScript Intersections in Depth

An intersection type combines object types into one type that demands every member. A value of the combined type carries the members of all the parts.

Two types combined into one

The alias joins a name part and a price part with &. The object must carry both members to fit the combined type.

type NamedPart = { itemName: string };
type PricedPart = { price: number };
type Product = NamedPart & PricedPart;
const pen: Product = { itemName: "Pen", price: 2 };
console.log(pen.itemName);
console.log(pen.price);

The mixin pattern with spread

A mixin is a small feature object that adds members to a base object. Spread merges the base record with the email and role features into one account.

type BaseRecord = { id: number; itemName: string };
type EmailFeature = { email: string };
type RoleFeature = { role: string };
type Account = BaseRecord & EmailFeature & RoleFeature;
const base: BaseRecord = { id: 7, itemName: "Mira" };
const account: Account = { ...base, email: "mira@example.com", role: "admin" };
console.log(account.id);
console.log(account.email);
console.log(account.role);

Conflicting members collapse to never

Both parts declare code, one as a string and one as a number. No value is both, so the combined member type is never and the assignment fails.

type TextCode = { code: string };
type NumericCode = { code: number };
type BothCodes = TextCode & NumericCode;
const entry: BothCodes = { code: "A1" };
console.log(entry.code);

An intersection as a parameter type

A parameter typed by an intersection receives an object with every member. The function reads members that come from both parts.

type HasId = { id: number };
type HasLabel = { labelText: string };
function describeEntry(entry: HasId & HasLabel): string {
  return entry.id + " " + entry.labelText;
}
console.log(describeEntry({ id: 4, labelText: "Notebook" }));

Example

type PersonPart = { fullName: string; age: number };
type JobPart = { jobTitle: string; salary: number };
type Employee = PersonPart & JobPart;
const worker: Employee = {
  fullName: "Ana Ruiz",
  age: 31,
  jobTitle: "Editor",
  salary: 5400,
};
console.log(worker.fullName);
console.log(worker.jobTitle);
console.log(worker.salary);

Key points

  • The & operator joins object types into a single intersection type.
  • A value of an intersection type must supply every member from every part.
  • The mixin pattern builds one object by spreading a base record and feature objects together.
  • Two parts that give one member different types make the type of that member never.
  • A never member accepts no value, so any assignment to that member fails.

In this example, the Employee type intersects a person part and a job part, and the worker object supplies every member from both parts.

Note

Spread copies members at run time, and the intersection type describes the finished object at compile time.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท TypeScript Playground

Exercise

One member is a string in one part of an intersection and a number in another part. What is the combined type of that member?