-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Typecast sometimes warns about an error when properties don't align #5853
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
Comments
I think the answer is that the value of As of 1.6 and strict object literal checking, you cannot have excess properties... #185 covers the non-nullable type, which would cause |
@kitsonk, that is a very reasonable hypothesis. Sorry I forgot to include a case which possibly disproves it: // No error
const z = { a: 'a', c: 'c' } as { a: string } |
Ok, I give up! 😄 const z: { a: string } = { a: 'a', c: 'c' }; // Errors
|
I do not understand TypeScript very well, but it is my understanding that |
Type assertions, either using the postfix // not an error, because { a: string, b: string } is assignable to { a: string }
const x = { a: 'a' } as { a: string, b: string}
// error, because neither { a: string, c: string } is assignable to { a: string, b: string } nor { a: string, b: string } to { a: string, c: string }
const y = { a: 'a', c: 'c' } as { a: string, b: string }
// not an error, as { a: string, c: string } is assignable to { a: string }
const z = { a: 'a', c: 'c' } as { a: string }; You can find more information about type assertions in: https://github.com./Microsoft/TypeScript/blob/master/doc/spec.md#416-type-assertions Now, this was intentionally lose, to allow you to up cast and down cast. but normal assignments are checked in a more strict fashion. var ab : {a: string, b: string};
ab = { a: "a" }; // Error missing b
ab = { b: "b" }; // Error missing a
ab = { a: "a", b: "b" }; // OK One observation here is that object literals assignment does not fail if the target has optional properties that were not specified in the target, e.g.: var maybeC : {c? : string};
maybeC = { cc: "intentional?" }; as per the basic algorithm this is fine, as the target hope that helped. |
Okay, I understand that this is the designed functionality, and thus, not a bug. Thank you for a very thorough explanation in terms of the implementation. If it's not too impolite, may I ask you for explanations in terms of use cases? But what about the opposite? In |
Fair questions. Let's think about some concrete examples that have the same type relationships as the types in your examples const x = { a: 'a' } as { a: string, b: string} This example might be rewritten as const myTextbox = document.getElementById('myInput') as HTMLInputElement; Here we got back an Now this example: const y = { a: 'a', c: 'c' } as { a: string, b: string }. We might rewrite this as: const myTextbox = document.getElementById as HTMLInputElement; This code is not good. We forgot to invoke the function. You might say "But in my example, the types had a property in common", but this is also true of the types here -- both the function and the The point with this example is that not all type assertions should be allowed. The assertion needs to be at least somewhat reasonable. If you really, really know what's going on, you can chain together two type assertions to work around this, but I have never seen a case where that is required when the definition for the type is actually correct. |
This has been very helpful, @RyanCavanaugh. It still seems partially inconsistent theoretically, but the practical benefits are very reasonable. It is notable that your explanation is very inheritance oriented. What about the interface-heavy workflow? interface AttachedToDom { getDomTree: Function }
interface ValueContaining { getValue: () => string }
const myTextbox = getAttachedDomElement('myInput') as ValueContaining
// getAttachedDomElement returns AttachedToDom Pardon my poor attempt at coming up with proper interfaces, I hope you see the point where the interface-based workflow is far less likely to have the cast be strictly up or down. P.S. It seems this mini-essay of your would be very valuable, if added to the TypeScript Handbook. |
FWIW I use inheritance-based examples because the subtype/supertype relations are more clear. It seems better to write |
These are two great suggestions. Thank you a lot for your help. |
Some inconsistent behavior in errors on type casts.
In the following example, I expected consistency - either x and y is an error, or none of them are.
Playground
I do not understand how an extra parameter on
y
changes the behavior, seems a bug to me:The text was updated successfully, but these errors were encountered: