Intersection types

When Anders Hejlsberg added intersection types to TypeScript for the first time, he defined them as follows:

"Intersection types are the logical complement of union types. A union type A | B represents an entity that has either type A or type B, whereas an intersection type A & B represents an entity that has both type A and type B."

The following example declares three interfaces named A, B, and C. Then it declares an object named abc, whose type is the intersection type of the interfaces A, B, and C. As a result, the abc object has properties named a, b, and c, but not d:

interface A { a: string } 
interface B { b: string } 
interface C { c: string } 
declare let abc: A & B & C; 
abc.a = "hello"; // OK 
abc.b = "hello"; // OK 
abc.c = "hello"; // OK 
abc.d = "hello"; // Error 

Intersection types can also be applied to subproperties:

interface X { x: A }
interface Y { x: B }
interface Z { x: C }
declare let xyz: X & Y & Z;
xyz.x.a = "hello"; // OK
xyz.x.b = "hello"; // OK
xyz.x.c = "hello"; // OK
xyz.x.d = "hello"; // Error

They can also be applied to functions:

type F1 = (x: string) => string;
type F2 = (x: number) => number;
declare let f: F1 & F2;
let s = f("hello"); // OK
let n = f(42); // OK
let t = f(true); // Error

The properties available in one or all the types present in the intersection type are considered valid:

We can appreciate this behavior in the following example:

interface Supplier {
orderItems(): void;
getAddress(): void;
}

interface Customer {
sellItems(): void;
getAddress(): void;
}

declare let person: Supplier & Customer;
person.getAddress(); // OK
person.orderItems(); // OK
person.sellItems(); // OK