Skip to content

Unexpected behavior of union of interfaces sharing property with the same name. #7780

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
MrQubo opened this issue Apr 1, 2016 · 1 comment
Labels
Question An issue which isn't directly actionable in code

Comments

@MrQubo
Copy link

MrQubo commented Apr 1, 2016

TypeScript Version:

1.8.9

Code

Starting point:

type Type = 'foo' | 'bar';

interface FieldProto {
    type: Type;
}

interface FooField extends FieldProto {
    type: 'foo';
    foo?: string;
}

interface BarField extends FieldProto {
    type: 'bar';
    bar?: string;
}

type Field = FooField | BarField;

First case:

let type: Type = 'foo';

let field: Field = {
    type: type
};

Second case:

let field: Field = {
    type: 'foo',
    bar: 'eggs'
};

Expected behavior:

Type { type: 'foo' | 'bar', bar: 'eggs' } shouldn't be assignable to type Field.
Type { type: 'foo' | 'bar' } should be assignable to type Field.
Type { type: 'bar', bar: 'eggs' } should be assignable to type Field.
Type { type: 'foo', bar: 'eggs' } shouldn't be assignable to type Field.

Actual behavior:

Both of types { type: 'foo' | 'bar', bar: 'eggs' } and { type: 'foo' | 'bar' } aren't assignable to type Field.
Both of types { type: 'bar', bar: 'eggs' } and { type: 'foo', bar: 'eggs' } are assignable to type Field.

First case compiles with an error:

test3.ts(21,5): error TS2322: Type '{ type: "foo" | "bar"; }' is not assignable to type 'FooField | BarField'.
  Type '{ type: "foo" | "bar"; }' is not assignable to type 'BarField'.
    Types of property 'type' are incompatible.
      Type '"foo" | "bar"' is not assignable to type '"bar"'.
        Type '"foo"' is not assignable to type '"bar"'.

Second case compiles without an error.

@mhegazy
Copy link
Contributor

mhegazy commented Apr 28, 2016

These samples behave as i would expect.

Type { type: 'foo' | 'bar', bar: 'eggs' } shouldn't be assignable to type Field.

and it is.

Type { type: 'foo' | 'bar' } should be assignable to type Field.

Not relay. type { type: 'foo' | 'bar' } is not assignable to neither FooField nor BarField. it is easy to see why both are the same if you have more than one property. e.g:
{a : string | number, b: string | number } is not assignable to {a: string, b: string} | {a: number, b: number}. you can see more discussion about this in #7274

Type { type: 'bar', bar: 'eggs' } should be assignable to type Field.

and it is.

Type { type: 'foo', bar: 'eggs' } shouldn't be assignable to type Field.

It is not assignable to BarField, since type is not "bar", but it is assignable to FooField, nothing in FooField says that bar can not be there. The excess property checking is done over names, and not types, so it is not triggered here.

@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Apr 28, 2016
@mhegazy mhegazy closed this as completed May 20, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

2 participants