'TypeScript user-defined type guard doesn't discriminate for union with optional property

I have two types very similar except for an optional property

type Interval = { start: Date; end: Date; }
type IntervalOpenEnded = { start: Date; end?: Date; }

I want to be able to discriminate them so I've created an user-defined type guard

function isOpenEnded(interval: Interval | IntervalOpenEnded): interval is IntervalOpenEnded {
    return "end" in interval && interval.end != null;
}

For some reason, the compiler won't be able to discriminate this way

function thisDoesntWork(interval: Interval | IntervalOpenEnded) {
    if (isOpenEnded(interval)) {
        // interval here is still Interval | IntervalOpenEnded
        console.log(interval.end);
        throw new Error();
    }

    // this won't compile as the type of interval is "never"
    console.log(interval.end);
}

Discriminating outside of a user-defined type guard will work a bit better as it will compile

function thisWorks(interval: Interval | IntervalOpenEnded) {
    if ("end" in interval && interval.end != null) {
        // here interval is still Interval | IntervalOpenEnded
        console.log(interval.end);
        throw new Error();
    }

    // this will compile and interval is Interval | IntervalOpenEnded
    console.log(interval.end);
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source