Objects and unions

Combine requirements with intersections

Create a type that must satisfy two object shapes and recognize when one explicit object type is easier to read.

A union says a value is one type or another. An intersection says a value is one type and another. It combines requirements: a value must satisfy every member.

type User = { id: number; name: string }
type Timestamped = { createdAt: Date }

type SavedUser = User & Timestamped

A SavedUser needs the properties from User and Timestamped:

const user: SavedUser = {
  id: 1,
  name: 'Ada',
  createdAt: new Date()
}

Leave out createdAt and the assignment fails: the value satisfies User but not Timestamped, so it is not the intersection.

Intersections are useful when independent concerns truly meet in one value. Timestamped can decorate users, posts, and comments without repeating the field in each type. A function that only cares about timestamps can accept Timestamped alone, and any SavedUser qualifies through structural typing.

Conflicting properties

Be careful with conflicting properties:

type A = { id: string }
type B = { id: number }
type Impossible = A & B

The id would need to be both a string and a number, so no ordinary value can satisfy it. TypeScript resolves the property to never, and every assignment of a real id fails:

Type 'string' is not assignable to type 'never'.

The compiler does not reject the Impossible type itself, only every attempt to build a value for it. If you see never appearing in an error about a property you defined twice, an intersection conflict is the usual cause.

When to prefer one explicit type

Deeply layered intersections also produce difficult error messages. A missing property in A & B & C & D gets reported against the whole chain, and you have to work out which member wanted it.

My advice: if the combined shape is a core domain object that you name, read, and discuss often, one explicit object type can be easier to read. Keep intersections for genuinely independent, reusable capabilities.

Exercise: combine { title: string } with { updatedAt: Date }, then intentionally omit one property and read the error.

Lesson completed

Take this course offline

Get every free book, course edition, and software download.

Get the download library →