Skip to content

Partially discriminated union with explicitly defined key loosens inferred typeΒ #55239

Closed as not planned
@cwoolum

Description

@cwoolum

Bug Report

Please feel free to change the title to make it more accurate. I wasn't sure what to call this

πŸ”Ž Search Terms

union narrow

πŸ•— Version & Regression Information

5.1.6

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

export type DomNodeStyle = ElementStyle | ImageStyle;

export type ElementStyle = {
    tagName: string;
    style: { key: string; value: string }[];
    children: (ElementStyle | ContentStyle)[];
};

export type ContentStyle = { content: string };

export type ImageStyle = {
    tagName: 'img';
    imageSource: string | null;
    style: { key: string; value: string }[];
    children: (ElementStyle | ContentStyle)[];
};

const image = {
    tagName: 'img',
    imageSource: 'https://example.com/image.jpg', // This is correct. Compiler requires `imageSource` because tagName is `img`.
    style: [],
    children: []
};

function doSomeWork(node: DomNodeStyle) {
    if (image.tagName === "img") { // Narrowing is not occurring correctly
        console.log(image.imageSource) // Error message: Property 'imageSource' does not exist on type 'ElementStyle'
    }
}

πŸ™ Actual behavior

For a partially discriminated union, when trying to access a narrowed field value, the compiler does not properly narrow the type. This forces the user to use the in operator to determine if the field exists. When instantiating the object though, the compiler does correctly infer that the field from the narrowed type needs to exist.

πŸ™‚ Expected behavior

I would expect the compiler to properly narrow the type if the explicitly defined union is set. In this case, if tagName is img, the compiler should infer that imageSource is required and available. If tagName is any other string value, the compiler should fall back to ElementStyle for the 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