TypeScript: Extending vs anding vs oring
I felt like this could do with an explanation because for those who are just starting out with typescript, the difference between these three things may not be incredibly obvious. Hopefully I can explain in such a way that it’ll all make sense to you in just a few minutes.
Here are a couple of interfaces that we’ll use to demonstrate our extending etc.
interface IOne {
one: 1;
}
interface ITwo {
two: 2;
}
If we create another interface that extends IOne
, this new interface will also contain the key one
with value 1
, but we can define other keys in there too.
interface IThree extends IOne {
three: 3;
}
So this is equivalent to writing:
interface IThree {
one: 1;
three: 3;
}
When extending we cannot, however, override the value of the one
key, because it is very explicit.
interface IThree extends IOne {
one: 2; // Not happy
three: 3;
}
If the value of one
was something less specific like number
, we could define a more specific type in the extending interface.
interface IOne {
one: number;
}
interface IThree extends IOne {
one: 1; // Happy
three: 3;
}
Unfortunately, as far as I know, there is no way to extend an interface and remove keys from the parent interface. Extending is, exactly as it sounds, only for adding things to an existing interface.
Using the &
operator for types is similar to extending, but simply combines both of the types.
type TThree = IOne & ITwo;
This type will contain both of the keys: one
and two
.
This is equivalent to writing:
interface IThree {
one: 1;
two: 2;
};
The |
operator in types is best utilized when defining function parameters. It essentially means that an argument may be of any of the types in its definition. E.g.
type TOneOrTwo = IOne | ITwo;
function plusOne (input: TOneOrTwo) {
}
This function will only accept objects that match either the interface of IOne
or ITwo
.
plusOne({one: 1}); // Happy
plusOne({two: 2}); // Happy
plusOne({}); // Not happy
plusOne({one: 1, two: 2}); // Not happy
In order figure out which of the types the input is, you’d have to use type guards as you cannot access either the key one
or two
as they do not exist on both types. You can read a bit more about type guards in this post.