Union of two interfaces rejects keys that should be acceptable #18421
Copy link
Copy link
Closed
Labels
Working as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug
Description
Update: I submitted a bad code sample the first time around — I've updated this to reflect something that seems actually broken.
--
TypeScript Version: 2.5.2
Code
interface ThingTypeOne {
type: 'one';
}
interface ThingTypeTwo {
type: 'two';
}
type ThingType = 'one' | 'two';
type Thing = ThingTypeOne | ThingTypeTwo;
function makeNewThing(thingType: ThingType): Thing {
return {
type: thingType
};
}Expected behavior:
No error
Actual behavior:
foo.ts(14,3): error TS2322: Type '{ type: ThingType; }' is not assignable to type 'Thing'.
Type '{ type: ThingType; }' is not assignable to type 'ThingTypeTwo'.
Types of property 'type' are incompatible.
Type 'ThingType' is not assignable to type '"two"'.
Type '"one"' is not assignable to type '"two"'.
It looks to me like the issue is that the compiler doesn't figure out the union of keys within the interfaces. If that's true, it seems strange to me that this is a breaking error since this code should work just fine.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Working as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug
Activity
ahejlsberg commentedon Sep 12, 2017
I'm pretty sure you meant to say:
[-]`Partial` of union type disallows one side of the union[/-][+]Union of two interfaces rejects keys that should be acceptable[/+]dylanpyle commentedon Sep 12, 2017
Anders Hejlsberg (@ahejlsberg) Yep sorry about that, I've updated the original description with a new failing code sample that should illustrate this better, and updated the issue title to match.
olegdunkan commentedon Sep 13, 2017
Dylan Pyle (@dylanpyle)
{ type:"one" } | { type:"two" }is not the same as{ type:"one" | "two" }mhegazy commentedon Oct 3, 2017
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.
jcalz commentedon Oct 30, 2017
olegdunkan et al,
Could someone explain why
{ type:"one" } | { type:"two" }is not the same as{ type:"one" | "two" }? I understand that the compiler is not recognizing the identity, but they seem identical to me. Can you produce an object of one type that is not an object of the other? I am unable to conceive of one.EDIT: Ah, this issue is a duplicate of #12052, in which it is mentioned by Anders Hejlsberg (@ahejlsberg) that these two types are equivalent, but the compiler doesn't establish the equivalence because it is rare in practice to encounter a union type that can be represented as a non-union type with a union property. Now I have a good answer to an SO question.