Skip to content

Can cast to partial interface of types unless you also provide an optional member #12187

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
lucasray opened this issue Nov 11, 2016 · 7 comments
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@lucasray
Copy link

TypeScript Version: 2.0.X / 2.1.X

Code

interface Foo {
  required1: string;
  required2: string;
  optional?: string;
}

const foo1 = { required1: "hello" } as Foo; // succeeds
const foo2 = { required1: "hello", optional: "bar" } as Foo; // fails

Expected behavior:
Expect similar behavior in the above two casts -- either for the foo1 cast to also fail (ideal, as required2 is missing), or for the foo2 cast to succeed.

Actual behavior:
Actual behavior in comments -- foo1 cast succeeds while foo2 fails.

@DanielRosenwasser
Copy link
Member

I feel like @JsonFreeman has brought this up before.

@JsonFreeman
Copy link
Contributor

This does seem like a familiar problem, though I am surprised that this does not work. Is there a type relation dedicated to checking type assertions?

I suspect it has to do with the fact that the object is being converted to a type where one property optional is less present, but another property required2 is more present. In general the limitations on type assertions have been because even for types that seem obviously related, the relation does not lean unanimously in any one direction.

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Nov 12, 2016

We use the comparable relationship for each direction, which is mostly just assignability except that a type S is comparable to a union T1 | ... | Tn, if S is assignable to any Ti.

That's exactly it I think. I dug up the issue I was thinking about: #1447

@JsonFreeman
Copy link
Contributor

I think one option is to simply ignore optionality in the comparable relation. That is a targeted fix, though it might break other cases.

Another option is to try to generalize this. When you check assertions, you could ask the question: Is there any value that can simultaneously inhabit both of these types. This might be too broad because usually the answer will be yes, you could just intersect the two types. For objects that are completely unrelated, an object that aggregated both of their properties would inhabit both types.

It feels like for object types, it might be useful to think about this in a similar way to the rule about excess properties. There was nothing type theoretic that said excess properties were not allowed, but if you passed an object with excess properties, it was likely that the user had misspelled a property. In other words, what is the mistake that this check is trying to catch?

@DanielRosenwasser
Copy link
Member

I think it is close in spirit to excess property checking.

I think one option is to simply ignore optionality in the comparable relation. That is a targeted fix, though it might break other cases.

I was thinking about this as well - comparability is about the idea that the source and target may actually be the same at runtime.

@DanielRosenwasser
Copy link
Member

Check out #12202 for a fix.

@DanielRosenwasser DanielRosenwasser added the Bug A bug in TypeScript label Nov 12, 2016
@DanielRosenwasser DanielRosenwasser self-assigned this Nov 12, 2016
@lucasray
Copy link
Author

Great, thanks for the quick turnaround and fix!

@mhegazy mhegazy added this to the TypeScript 2.1.3 milestone Nov 14, 2016
@mhegazy mhegazy added the Fixed A PR has been merged for this issue label Nov 14, 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
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

4 participants