However, is the resulting type of the | not actually an intersection, and that of & a union?
No. These concepts come from functional programming and type theory, so to understand them, it helps if you think of types in a way that's more in line with that.
Informally, think of a type as of a set of all the instances of that type. For example, the
string type is conceptually a set of all concrete strings that you can construct, like
"", "foo", "bar", "Hello, world!", etc. When you create an instance, it's like you are picking a single item from that set. If you come across some value, saying that it's of a certain type is like saying that it is contained in the set labeled by the type's name.
Now, when you are define a union type
number | string | boolean, you are practically doing a union operation on those three sets; you are saying that a variable of that type can be a number or a string or a bool - i.e., it can take some value from any of those three sets. In other words, you are pulling from a set that's a union of the three.
Therefore, you can have a bunch of instances (objects), and you can group them into sets based on the operations they support. Some will belong to more then one set, like in the image below. When you write
Person & Serializable & Loggable, you are restricting the set of possible values to only those that belong to all three of these sets simultaneously (support all these operations at the same time). I.e., you are considering only those possible instances that are in their intersection.