I have been reading book effective typescript and there is this paragraph there with code which is not clear to me :
1.
interface Person {
name: string;
}
interface Lifespan {
birth: Date;
death?: Date;
}
type PersonSpan = Person & Lifespan; // why not never type ?
The &
operator computes the intersection of two types. What sorts of values belong to
the PersonSpan type?
On first glance the Person and Lifespan interfaces have no properties in common, so you might expect it to be the empty set (i.e., the never type). But type operations apply to the sets of values (the domain of the type), not to the properties in the interface. And remember that values with additional properties still belong to a type. So a value that has the properties of both Person and Lifespan will belong to the intersection type:
const ps: PersonSpan = {
name: 'Alan Turing',
birth: new Date('1912/06/23'),
death: new Date('1954/06/07'),
}; // OK
what if declare
type newPersonSpan = Person | Lifespan; // what are the possible values we can assign now ?
could someone please explain this in more layman language
CodePudding user response:
The short version is: to be a Person & Lifespan
, an object must have all the properties defined in Person
, and it must also have all the properties defined in Lifespan
.
Long version: The book is describing one way you can conceptualize the way that &
works: as the intersection of sets. First, let's start with what this means:
interface Person {
name: string;
}
To be a Person
, a variable must be an object, and that object must have a name property that is a string
. Simple enough, but it's important to point out: it can also have any number of extra properties, and still be a Person
. So all of the following objects are compatible with Person
:
{ name: 'bob' }
{ name: 'alice', age: 30 }
{ name: 'eve', birth: new Date() }
You can think of types as being
So from the examples i gave, { name: 'eve', birth: new Date() }
is in the intersection. It is both a Person, and a Lifespan. The rest of the examples are only in one, not the other, for one reason or another. Eg, { name: 'bob' }
is not a Lifespan because it has no birth, and { birth: new Date(), name: true }
is not a Person because its name is the wrong type.
CodePudding user response:
Think about it this way:
- There are many entities named Mickey.
- There are many mice.
- Mickey Mouse is in the set that is the intersection of both the set of Mickies and the set of mice.
It works the same way for Person
and Lifespan
: there's a set of types that are Persons and there's a set of types that are Lifespans and there's an an intersection of types that are both Persons and Lifespans.
Remember that Typescript is structurally typed. If I have a type Foo and a type Bar
type Foo = { a: number };
type Bar = { b: string };
then any object with an a
property that's a number counts as a Foo
, and any object with a b
property that's a string counts as a Bar
, and a Foobar
(Foo & Bar
) is any object that is both a Foo
and a Bar
, i.e. has an a: number
and a b: string
.