Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: understanding union and Intersection types

I am trying to get an intuition about Union and Intersection types in typescript, but I can't figure out this case: Playground Link

interface A {
    a: number;
}

interface B{
    b: boolean;
}



type UnionCombinedType = A | B;
type IntersectionType = A & B;

const obj: UnionCombinedType = {
    a: 6,
    b: true,
}

const obj2: IntersectionType = {
    a: 6,
    b: true,
}

Why am I allow to put both values in the intersection type? The intersection between the two interfaces is empty. If I read the & as AND then it's clear to me why it allows me to add both props, but then I should read the | keyword as OR and I would expect it to allow me to assign only a or b but not both.

Can someone give me some intuition about those types?

like image 874
niryo Avatar asked Apr 22 '20 16:04

niryo


People also ask

Can I check a type against a union type in TypeScript?

We can differentiate between types in a union with a type guard. A type guard is a conditional check that allows us to differentiate between types. And in this case, a type guard lets us figure out exactly which type we have within the union.

How do you define intersection types in TypeScript?

An intersection type is a type that merges several kinds into one. This allows you to combine many types to create a single type with all of the properties that you require. An object of this type will have members from all of the types given. The '&' operator is used to create the intersection type.

How do you handle union types in TypeScript?

TypeScript infers the return type of a function, hence, if a function returns more than one type of data, TypeScript will infer the return type to be a union of all the possible return types. If you wish to assign the function's return value to a variable, type the variable as a union of expected return types.

How do I compare types in TypeScript?

In Typescript, we have three ways to work with it using: typeof: the keyword helps to check values types, like boolean, string, number, etc. instanceof: the keyword to compare the object instance with a class constructor. type guards: The powerful way to check types using typescript feature language.


1 Answers

Given the following:

interface A {
    a: number;
    c: number;
}

interface B{
    b: boolean;
    c: number;
}

Expression of Union type A | B is assignable to either A or B. It must have properties from A or B (or both)

const oA: A | B = {
    a: 6,
    c: 6
}

const oB: A | B = {
    b: true,
    c: 6
}

const oC: A | B = {
    a: 6,
    b: true
    c: 6
}

But what operations does a type like A | B have? Only these that belong to both A and B

oA.c = 1; // valid

Intersection type A & B, if it is assignable to both A and B (and therefore must have properties of both A and B).

const obj: A & B = {
    a: 6,
    b: true
}

Update

You ask "why does A & B in your example can take b prop? it's not assignable to type A"

This is clearly not true. Any type that has all properties of A can be assigned to A. Extra properties make no harm:

const aAndExtraProp = {
  a: 6,
  d: 6
};

const ca0: A = aAndExtraProp;

You are probably confused by Excess Property Checks for object literals:

Object literals get special treatment and undergo excess property checking when assigning them to other variables, or passing them as arguments. If an object literal has any properties that the “target type” doesn’t have, you’ll get an error:

const ca1: A = {
  a: 6,
  d: 6 //ERROR
};
like image 56
Lesiak Avatar answered Oct 18 '22 12:10

Lesiak