Skip to content

Make array.includes () work with discriminated union type inference work #49559

Closed
@wenq1

Description

@wenq1

I find it hard to get Array.includes () as a method to type-guard or narrowing discriminated unions


interface Circle {
        kind:           "circle";
        radius:         number;
}

interface Square {
        kind:           "square";
        sideLength:     number;
}

type Shape = Circle | Square;


// "Improved" Array.includes, reference: https://fettblog.eu/typescript-array-includes/
// However, still not working with the parent type
function elementBelongsToArr2<T>(value: unknown, allowedValues: ReadonlyArray<T>): value is T {
        return (allowedValues as ReadonlyArray<unknown>).includes (value);
}

function getArea (shape: Shape) {
        let     area;
        // Attempt 1 - ok
        if (shape.kind === 'circle') {
                let     kind1  = shape.kind;
                //      ^? ("circle"), correct type
                area    = Math.PI * shape.radius ** 2;
                //                  ^? (Circle), correct type
        }

        let     circleKinds     = ["circle"] as const;
        // Attempt 2 - fail
        if (circleKinds.includes (shape.kind)) {        // won't compile here
                let     kind1   = shape.kind;           
                //      ^? ("circle"|"squared"), wrong type
                area    = Math.PI * shape.radius ** 2; 
                //                  ^? (Shape), wrong type
        }

        // Attempt 3 - fail
        if (elementBelongsToArr2 (shape.kind, circleKinds)) {
                let     kind1   = shape.kind;           // correct kind
                //      ^? ("circle"), correct type
                area    = Math.PI * shape.radius ** 2;  // still incorrect shape
                //                  ^? (Shape), wrong type
        }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions