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

Inconsistent error messaging when assigning a value to an interface type #13582

Closed
jednano opened this issue Jan 19, 2017 · 4 comments
Closed
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@jednano
Copy link
Contributor

jednano commented Jan 19, 2017

TypeScript Version: 2.1.1 / nightly (2.2.0-dev.201xxxxx) or whatever's on the TypeScript Playground today.

Code

interface Point {
    x: number;
    y: number;
};

const a = { x: 5, y: 5, z: 5 };
const b: Point = a;

Expected behavior:

An error is thrown.

Type '{ x: number; y: number; z: number; }' is not assignable to type 'Point'.
Object literal may only specify known properties, and 'z' does not exist in type 'Point'.

Actual behavior:

No errors thrown, but why? What is b: Point really saying? That b is of type Point or that b implements Point? Behaviorally, without throwing an error here, it's telling me that b implements Point. Syntactically, however, it's telling me that b is of type Point, which should be more strict, no?

Sorry for my lack of grammar.

Potential inconsistent behavior:

const c: Point = { x: 5, y: 5, z: 5 };

Expected and actual behavior:

An error is thrown.

Proposal

Be consistent? I don't see why x: T = y should be any different than a = y; x: T = a;. Is it crazy to request the following syntax for the implements case?

const a implements Point = { x: 5, y: 5, z: 5 }; // OK
const a: Point = { x: 5, y: 5, z: 5 }; // Error

Just trying to offer a solution here, but I hate that it's not backwards compatible. I couldn't find any existing issues or discussions about this.

@RyanCavanaugh
Copy link
Member

Consistency is not a pure virtue; it is only as good as the value it provides.

We could ignore excess properties in initialized variables. This used to be how it worked; people correctly complained that this was terrible behavior because if you declare a Point and initialize it with a z, we know the z effectively "goes missing"; from the type system's point of view that property initializer is evaluated for no reason and then vanishes forever. This was especially bad with optional properties as it's easy to misspell the property name and not get an error. It would be absolute madness to think about disallowing const b: Point = a; so I won't even go into that.

const a implements Point = { x: 5, y: 5, z: 5 }; // OK

What are your use cases for this?

@RyanCavanaugh
Copy link
Member

See also #7481

@mhegazy mhegazy added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jan 19, 2017
@jednano
Copy link
Contributor Author

jednano commented Jan 19, 2017

@RyanCavanaugh this issue was in response to this discussion on Flow about whether TypeScript interfaces could be compared with the exact object type in Flow.

@jednano jednano closed this as completed Jan 19, 2017
@magnushiie
Copy link
Contributor

As I propsed #7481, I would also like to comment that #7481 would not address this, as record widening is an upcast. What @jedmao looks for is #12936.

@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
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants