Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
louiebert opened this issue Jun 11, 2020 · 3 comments
Labels
Duplicate An existing issue was already created

Comments

@louiebert
Copy link

louiebert commented Jun 11, 2020

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.

@MartinJohns
Copy link
Contributor

MartinJohns commented Jun 11, 2020

Duplicate of #12184.

@louiebert
Copy link
Author

louiebert commented Jun 11, 2020

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

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jun 12, 2020
@typescript-bot
Copy link
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
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants