Search code examples
typescriptunionintersection

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?


Solution

  • 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,
        c: 1
    }
    

    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,
      c: 1,
      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,
      c: 1,
      d: 6 //ERROR
    };