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

Cast permitted with missing properties on object literals #13788

Closed
mathias999us opened this issue Jan 31, 2017 · 3 comments
Closed

Cast permitted with missing properties on object literals #13788

mathias999us opened this issue Jan 31, 2017 · 3 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@mathias999us
Copy link

TypeScript Version: 2.1.1 / nightly (2.2.0-dev.201xxxxx)

Code

interface ITestOne {
    a: string;
    b?: string;
}

var test1: ITestOne = {} as ITestOne; // ALLOWED - Why is this allowed?
var test2: ITestOne = { b: 'blah' } as ITestOne; // ALLOWED - Why is this allowed?
var test3: ITestOne = { b: 'blah', x: 'meh' } as ITestOne; // ERROR - Property a is missing

Expected behavior:

Expected behavior is that test2 case is not permitted. NOTE: This was working correctly as of TypeScript 1.7.

Test3 is an example of how to perturb the "correct" behavior.

I have not been able to find any documentation about why test1 is allowed. One could make the case for filling out an empty object literal after it has been instantiated empty, but this seems like a dangerous thing to allow. Again it permits the case where we have an object of ITestOne that does not meet the interface definition.

Actual behavior:
test2 passed compiler checks, but produces an invalid object literal without property a.

See SO post for some further background:
http://stackoverflow.com/questions/41941125/intellisense-with-union-types

@mhegazy
Copy link
Contributor

mhegazy commented Jan 31, 2017

Type Assertion spec

In a type assertion expression of the form < T > e, e is contextually typed (section 4.23) by T and the resulting type of* e* is required to be assignable to T, or T is required to be assignable to the widened form of the resulting type of e, or otherwise a compile-time error occurs. The type of the result is T.

What type assertion does, it tells the compiler to "shut up" and trust you. The operator behaves both as an upcast and as a downcast operator. The only check is that the one of the types is assignable to the other.

In the example above, for test: {a: string, b?:string} is assignable to {} (which requires no arguments); for test2 {a: string, b?:string} is assignable to {b:string}, since the type of the only required argument in the target b matches. for test3 neither {a: string, b?:string} is assignable to {b:string, x:string} since it is missing x nor {b:string, x:string} to {a: string, b?:string} since it is missing a.

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

Thank you - this is very helpful. At this risk of turning this into a question thread, it's not clear to me why asserting that { a:string, b?:string } is assignable to {} is useful in the case where the assignment is the other way around (from {} to { a:string, b?:string }). i.e. Why does it matter if the target type is assignable to the source type? Why check at all?

@mhegazy
Copy link
Contributor

mhegazy commented Jan 31, 2017

At this risk of turning this into a question thread, it's not clear to me why asserting that { a:string, b?:string } is assignable to {} is useful in the case where the assignment is the other way around (from {} to { a:string, b?:string }). i.e. Why does it matter if the target type is assignable to the source type? Why check at all?

Not sure i understand your question here. the compiler is trying to help verify that this is either a valid up cast or down cast, and not two completely unrelated types. beyond that, it is up to you to decide whether this was a valid conversion or not.

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

2 participants