The introduction

  1. Have you ever wondered what the word “crossover” actually means in the genre of crossover? Why is it called crossover type?
  2. See the following example:
interface A {
  x: number;
  y: number;
}
interface B {
  y: number;
  z: number;
}
type U = A & B;
type I = A | B;
Copy the code

When using attributes specifically, we will find that in the ts prompt, the cross type U has three attributes x,y and Z, while the union type I only has the y attribute. Where is the “union” embodied?

  1. This paper tries to understand the principles and patterns of its design from the perspective of collection (personal thinking)

The body of the

Types and collections

Here we need to go back to what “type” is. Putting aside the term “instantiation,” from a collection perspective, a type should refer to a collection of values with specific properties.

In Typescript, for example, the number type is a collection of all numbers, the string type is a collection of all strings, the literal type 1 is a collection of only one element 1, and the literal type “1” is a collection of only one element “1”.

However, in object, the concept of set is very confusing. I have never understood why a subclass is a subset of its parent class. It is clear that a subclass has more properties and methods than its parent class.

Here’s a myth I’ve been stuck in. Here’s an example:

interface A {
  x: number;
}
interface B extends A {
  y: number;
}
const obj = {
  x: 1.xx: 2.xxx: 3};const a: A = obj;
const b: B = obj; // error
Copy the code

Obviously, the variable a is of type A, but in fact the object it represents has properties x,xx, and XXX. Obviously, an important point can be made here: an object type only requires that the object it describes have these properties, not necessarily have and only have these properties.

On this basis, it is not difficult to understand that type B is A subset of type A, because A is the set of all objects that have property X (as long as there is, an object may have any other property), and B requires an object to have property Y in addition to having property X, which is obviously stricter than that of A. B is obviously A subset of A.

That is, an object type is a collection of objects, not a collection of properties. An object is a member of the type as long as it has all the properties it describes

Note: Typescript is not entirely based on mathematical definitions of collections. For actual type safety, an error will be reported if the assignment is changed to a literal object

const a: A = {
  x: 1.xx: 2.// ERROR
  xxx: 3.// ERROR
};
Copy the code

Simple operations on the intersection type and union type operators

Intersection types. For the purposes of this article, it might be more appropriate to translate this as Intersection types.

The Union types are known as Union types. For the purposes of this article, it may be more appropriate to translate them as Union types.

From the point of view of collection, &, | operators of various calculation results:

type A = 1 | 2 | 3;
type B = 2 | 3 | 4;
type C = A & B; // C为: 2 | 3
type D = A & number; // D为: 1 | 2 | 3
type E = A | number; // E is: number
type F = number & string; // F is never
Copy the code

Type A minus E is just A set operation. As for type F, although the official definition of “never” is only “the type that will not appear”, I think it is the idea of “empty set” that exerts a subtle influence on them, and they regard never as an empty set.

As for the several operational properties granted by the government, it is estimated that the idea of set is also influencing these operational properties, which are obvious:

For the intersection operator & :

  1. Uniqueness:A & AIs equivalent toA.
  2. Satisfies the commutative law:A & BIs equivalent toB & A(Function calls and constructors are slightly different, as described below).
  3. Satisfy associative law:(A & B) & CIs equivalent toA & (B & C).
  4. Parent type convergence: if and only ifBAOf the parent type,A & BIs equivalent toA.

For operator and set | :

  1. Uniqueness:A | AIs equivalent toA.
  2. Satisfies the commutative law:A | BIs equivalent toB | A.
  3. Satisfy associative law:(A | B) | CIs equivalent toA | (B | C).
  4. Subtype convergence: if and only ifBAOf subtypes,A | BIs equivalent toA.

Note: Typescript uses Supertype and Subtype, not Superclass and Subclass. A and B are not necessarily Class but they can also be type or interface. I’m sure you can understand the difference between these nouns.

Advanced operations on the intersection type and union type operators

Intersection types Intersection types

  • &|Has a higher operational priority
  • If the typeAThe properties of thepIs a type ofXType,BThe properties of thepIs a type ofY, then the intersection typeA & BIs the corresponding property inpX & Y
  • Intersection typeA & BHave a typeABAll properties of (i.eThe union of properties). Again, intersection typeIs not the intersection of a set of properties, butThe intersection of a collection of objects. (The more attributes a type has, the more constraints it has, and an object can be classified as an intersection type only if it satisfies the union of these conditions.)
  • ifABIs a function type, soA & BRepresents an overloaded function, and the sequence of collection operation is the order of function signature of the overloaded function. (for example, in vscode intelligent prompt, the type of the first overloaded function prompt will beAType)
  • ifAIs an object type,BIs the original data type (string.numberThese), representing the raw data types of “special Tags”

The last two points may be understood in conjunction with actual code:

  1. The intersection type of functions is overloaded:
type M = (a: number) = > number;
type N = (a: string) = > string;

function overload(a: number) :number;
function overload(a: string) :string;
function overload(a: number | string) {
  return a;
}

let m: M = overload; // OK
let n: N = overload; // OK
let mn: M & N = overload; // OK
Copy the code

Obviously type M describes functions that can take a number and return a number. Note that can, rather than can and can only, is similar to the previous object types. If type M is a member of set M, and type N is a member of set N, then it must be an element of the intersection of M and N.

So the final representation would be: the intersection type of the function type is an overloaded function

  1. Although the intersection of the object type and the original data type should be an empty set according to set logic, in TS it ends up beingpackingAnd the properties of the object type. This is actually for another purpose entirely:nominal, even if the “type alias” (type) has uniqueness (or tag), officialFAQIs mentioned
// Strings here are arbitrary, but must be distinct
type SomeUrl = string & {'this is a url': {}};
type FirstName = string & {'person name': {}};

// Add type assertions
let x = <SomeUrl>' ';
let y = <FirstName>'bob';
x = y; // Error

// OK
let xs: string = x;
let ys: string = y;
xs = ys;
Copy the code

This makes sense in some cases: function A actually takes A string, but only wants to take A string that function B has processed as an argument. Then you can use this feature to achieve:

function B(str:string){
  return str as string & {__SPEC__: 'SPEC'}}function A(str: string & {__SPEC__: 'SPEC'}){... }Copy the code

Union types:

  • If the typeAThe properties of thepIs a type ofXType,BThe properties of thepIs a type ofY, then the union typeA | BIs the corresponding property inpX | Y
  • And set typeA | B Must havetypeABThe duplicate property of (i.eIntersection of properties). Here, too, from a practical, type-safe point of view, it is important to know which element in the intersection belongs toAorBIn the case of,During a visitTS can only give you a hint that they must both have properties, and therefore behave in an intersection;The assignmentNot much to say, meetABJust fine, standardAnd setConcept.
  • Function types are also represented by the concept of unions, which need no special understanding. The only thing worth noting is that this function is called when TS really cannot infer the type of the function: invert positions (arguments) take intersection types, and covariant positions (return values) take union types.

Note: covariant and contravariant

Afterword.

Discussion of crossover types: github.com/microsoft/T…

Crossover type PR: github.com/microsoft/T…

Discussion of union types: github.com/microsoft/T…

Union type PR: github.com/microsoft/T…

Discussion on Nominal: github.com/microsoft/T…

🤔 still has a hole to fill, so the “cross” is… ? 😂 After all, this is TS, not math, let’s call it terminology