Skip to content
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

error casting interface union field #20889

Closed
codemau5 opened this issue Dec 25, 2017 · 4 comments · Fixed by #30779
Closed

error casting interface union field #20889

codemau5 opened this issue Dec 25, 2017 · 4 comments · Fixed by #30779
Labels
Duplicate An existing issue was already created

Comments

@codemau5
Copy link

codemau5 commented Dec 25, 2017

TypeScript Version: 2.6.2

Code

interface A1 {
    type: "A1";
}
interface A2 {
    type: "A2";
}
type AU = A1 | A2;

function foo(obj1: AU) {
    const obj2: AU = {
        type: obj1.type
        /*
        Error TS2322:
        Type '{ type: "A1" | "A2"; }' is not assignable to type 'AU'.
            Type '{ type: "A1" | "A2"; }' is not assignable to type 'A2'.
            Types of property 'type' are incompatible.
            Type '"A1" | "A2"' is not assignable to type '"A2"'.
            Type '"A1"' is not assignable to type '"A2"'.
        */

    };
}

Expected behavior:
create a new object with the same value of the first object.

Actual behavior:
typescript error TS2322:
Type '{ type: "A1" | "A2"; }' is not assignable to type 'AU'.
Type '{ type: "A1" | "A2"; }' is not assignable to type 'A2'.
Types of property 'type' are incompatible.
Type '"A1" | "A2"' is not assignable to type '"A2"'.
Type '"A1"' is not assignable to type '"A2"'.

exampe in TypesSript Playground:
https://www.typescriptlang.org/play/index.html#src=interface%20A1%20%7B%0D%0A%20%20%20%20type%3A%20%22A1%22%3B%0D%0A%7D%0D%0Ainterface%20A2%20%7B%0D%0A%20%20%20%20type%3A%20%22A2%22%3B%0D%0A%7D%0D%0A%0D%0Atype%20AU%20%3D%20A1%20%7C%20A2%3B%0D%0A%0D%0Afunction%20foo(obj1%3A%20AU)%20%7B%0D%0A%20%20%20%20const%20obj2%3A%20AU%20%3D%20%7B%0D%0A%20%20%20%20%20%20%20%20type%3A%20obj1.type%0D%0A%20%20%20%20%7D%3B%0D%0A%7D%0D%0A

@jcalz
Copy link
Contributor

jcalz commented Dec 26, 2017

Duplicate of #12052 ?

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Dec 26, 2017

Using a type assertion actually does work here.

interface A1 {
    type: "A1";
}
interface A2 {
    type: "A2";
}

type AU = A1 | A2;

function foo(obj1: AU) {
    const obj2 = {
        type: obj1.type
    } as AU;
    // ^^^^
    // Here
}

@DanielRosenwasser DanielRosenwasser added the Duplicate An existing issue was already created label Dec 26, 2017
@codemau5
Copy link
Author

codemau5 commented Dec 26, 2017

@DanielRosenwasser the issue you labeled this as a duplicate of, is labeled as "intended behavior",
because { type: "A1" | "A2"; } !== { type: "A1"; } | { type: "A1" ; },
otherwise if we had more fields, we can get an unstable behaviour.

looking into it, I found that you do get unstable behavior using the fix you commented!!

interface A1 {
    typeA: "A1";
    typeB: "B1";
}
interface A2 {
    typeA: "A2";
    typeB: "B2";
}
type AU = A1 | A2;

function foo(obj1: AU, obj2: AU): AU {
    const obj3: AU = <AU>{
        typeA: obj1.typeA,
        typeB: obj2.typeB
    };
    return obj3;
}

const a1: A1 = {
    "typeA": "A1",
    "typeB": "B1"
}
const a2: A2 = {
    "typeA": "A2",
    "typeB": "B2"
}

const a3: AU = foo(a1, a2);

console.log(a3.typeA, a3.typeB);
// A1 B2

a3 is of type AU, but is in an invalid state!!

if you would try to create such an object, you would normally get this error:

const au: AU = {
    typeA: "A1",
    typeB: "B2"
};
/*
Type '{ typeA: "A1"; typeB: "B2"; }' is not assignable to type 'AU'.
  Type '{ typeA: "A1"; typeB: "B2"; }' is not assignable to type 'A2'.
    Types of property 'typeA' are incompatible.
      Type '"A1"' is not assignable to type '"A2"'.
*/

EDIT: I have issued a new issue for this new bug - #20896

@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants