typescriptdiscriminated-uniontypescript-never

How to discriminate an union against "never" type?


Let's say I have this union:

type TShape = {
    id: string;
}

type TCircle = TShape & {
    radius: number;
    size: never;
}

type TSquare = TShape & {
    radius: never;
    size: number;
}

The problem is how to discriminate the two possible types (in this case) using the radius field, for instance:

function getArea(shape: TCircle | TSquare): number {
    if (typeof shape.radius === "number") {
        return shape.radius * shape.radius * Math.PI;
    }
    else {
        return shape.radius * shape.size;  //no error?
    }
}

What I expect is a compiler error on the last calculation, because the radius field never exist on the TSquare type.

What's wrong with this and how to solve this problem?


Solution

  • Since TSquare does not need radius field you can declare it without it

    type TSquare = TShape & {
        size: number;
    }
    

    Then you can modify function and check if radius is defined.

    function getArea(shape: TCircle | TSquare): number {
        if ("radius" in shape) {
            return shape.radius * shape.radius * Math.PI;
        }
        else {
            return shape.radius * shape.size;  // this should be an error this time
        }
    }