Skip to content

Deconstructing a discriminated union with shared secondary property of different types #39026

Closed
@louiebert

Description

@louiebert

TypeScript Version: 3.9.2

Search Terms:
discriminated union, discriminated
Code

interface OptionOne {
    kind: "one";
    ambiguousProperty: number; // This property name is shared, but has a different type in each unioned interface
    isThisABug: boolean;
}

interface OptionTwo {
    kind: "two";
    ambiguousProperty: string; // This property name is shared, but has a different type in each unioned interface
    prettySureThisIsABug: boolean;
}

type OptionUnion = OptionOne | OptionTwo;

// This function is riddled with errors
const myDeconstructedFunc = ({kind, ambiguousProperty, ...otherParams}: OptionUnion) => {
    if (kind === "one") {
        const myLocalNum: number = ambiguousProperty;
        otherParams.isThisABug = true;

        console.log(myLocalNum); // So this thing is used
    } else if (kind === "two") {
        const myLocalString: string = ambiguousProperty;
        otherParams.prettySureThisIsABug = true;

        console.log(myLocalString); // So this thing is used
    }
};

// This function is error-free
const myNotDeconstructedFunc = (option: OptionUnion) => {
    if (option.kind === "one") {
        const myLocalNum: number = option.ambiguousProperty;
        option.isThisABug = true;

        console.log(myLocalNum); // So this thing is used
    } else if (option.kind === "two") {
        const myLocalString: string = option.ambiguousProperty;
        option.prettySureThisIsABug = true;

        console.log(myLocalString); // So this thing is used
    }
};

Expected behavior:
Both of these functions have the same behavior (ideally both compiling without errors)
Actual behavior:
myDeconstructedFunc has compile errors and can't discern the correct type inside a union isolating condition. myNotDeconstructedFunc handles this case just fine.
Playground Link:
Link here

Related Issues:
I didn't find any that were specifically for deconstructing a shared property that was typed differently per unioned interface.

Activity

MartinJohns

MartinJohns commented on Jun 11, 2020

@MartinJohns
Contributor

Duplicate of #12184.

louiebert

louiebert commented on Jun 11, 2020

@louiebert
Author

Upon further investigation, this doesn't need the condition of "shared property with different types". This repros as soon as the discriminant is deconstructed. If the discriminant is readonly, I feel like TS should be smart enough to retain its intellisense in the deconstructed discriminant.

interface OptionOne {
    readonly kind: "one";
    foo: number;
    isThisABug: boolean;
}

interface OptionTwo {
    readonly kind: "two";
    bar: string;
    prettySureThisIsABug: boolean;
}

type OptionUnion = OptionOne | OptionTwo;

// riddled with errors
const myDeconstructedFunc = ({kind, ...otherParams}: OptionUnion) => {
    if (kind === "one") {
        const myLocalNum: number = otherParams.foo;
        otherParams.isThisABug = true;

        console.log(myLocalNum); // So this thing is used
    } else if (kind === "two") {
        const myLocalString: string = otherParams.bar;
        otherParams.prettySureThisIsABug = true;

        console.log(myLocalString); // So this thing is used
    }
};

// no errors
const myNotDeconstructedFunc = (option: OptionUnion) => {
    if (option.kind === "one") {
        const myLocalNum: number = option.foo;
        option.isThisABug = true;

        console.log(myLocalNum); // So this thing is used
    } else if (option.kind === "two") {
        const myLocalString: string = option.bar;
        option.prettySureThisIsABug = true;

        console.log(myLocalString); // So this thing is used
    }
};

Playground link

typescript-bot

typescript-bot commented on Jun 14, 2020

@typescript-bot
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @MartinJohns@louiebert@RyanCavanaugh@typescript-bot

        Issue actions

          Deconstructing a discriminated union with shared secondary property of different types · Issue #39026 · microsoft/TypeScript