Search code examples
typescripttypescript3.0union-types

TypeScript union of type is resolved as intersection of types


I have this snippet

class J {
  constructor(public foo: number) {}
}

class B {
 constructor(public bar: string) {}
}

interface Cache {
 json?: J;
 binary?: B;
}

function test(key: "json" | "binary", data: J | B, obj: Cache) {
  obj[key] = data;
}

If you try this code in https://www.typescriptlang.org/play/, the line obj[key] = data; is having the following error

Type 'J | B' is not assignable to type 'J & B'. Type 'J' is not assignable to type 'J & B'. Property 'bar' is missing in type 'J' but required in type 'B'.

There's obviously something I am missing but I can't figure out what. Any idea?


Solution

  • Typescript can't tell which property of Cache you are trying to update, and when in doubt he considers that the value you are trying to insert should be able to fit both. Which the J | B can't.

    You could change your test function signature slightly to use Partial

    function test(update: Partial<Cache>, obj: Cache) {
        Object.assign(obj, update);
    }
    

    That way Typescript can be sure that the key/value pairs you are passing it are valid for the Cache class.