1

How would I achieve type inference in the following case:

type a = {
    foo: number;
    bar: string;
}

type b = {
    foo: string;
}

let baz: a | b;

if (baz.foo === 5) {
    baz.bar = "abc"; // baz type is still a | b, should be a
}
2

2 Answers 2

2

Apparently types cannot be inferred from the types of their properties, so you will need to define a type guard:

type a = {
    foo: number;
    bar: string;
}

type b = {
    foo: string;
}

let baz: a | b;

function isA(x: a | b): x is a {
    return typeof x.foo === 'number';
}

if (isA(baz) && baz.foo === 5) {
    baz.bar = "123";
}

The isA type guard will tell TypeScript that you have checked bazs type yourself. Below is another way to achieve this with casts, but here you still need to cast baz for every usage which is probably not the best way to do this.

if ((baz as a).foo === 5) {
    (baz as a).z = "123";
}

More information about type guards can be found in the TypeScript docs.

Sign up to request clarification or add additional context in comments.

Comments

0

baz type is still a | b, should be a

Actually what the TypeScript compiler does is restricts property access of all unified types (a | b) to properties that exist on all of them, thus, baz.bar does not even compile because bar does not exist on type b.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.