-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Type safety lost with generic return type when object spread is used #50559
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
Duplicate of #50185 |
@whzx5byb Is it a duplicate? Does this explain why the second implementation is actually type-safe while the first one isn't? |
Yes, per this comment in #50185:
Basically, the compiler inaccurately models the spread as The second case is typesafe and errors correctly because |
@fatcerberus Thank you for a detailed explanation. I still don't understand one thing. Since there's also a type constraint on I know that in fact function modify<T extends MyObject>(a: T): T {
const b = {
...a,
value: 'abc',
};
return b;
} |
You'd think so, but TS generally treats type parameters as opaque. There are some cases where it can fall back on the constraint (i.e. pretending that That said, even if the aforementioned reduction worked, it'd still be unsound - Thinking about this some more, you don't want to reject the expression on the basis that its type reduces to This would need a whole new type of check in the compiler, I think. |
Yup, I fully agree as long as we are talking about types. But a value of type
I wouldn't agree that returning a value of type |
Yep, the principle of explosion. It is indeed a tautology, but mathematically sound nonetheless.
We actually agree on this point: the spread expression produces a legal value and so should not be typed as |
You're saying this but my point is exactly about this thing not being a legal value because it has type |
|
Why is it "absolutely incorrect"? |
In short, because it doesn't throw. You're assuming |
In other words, |
@fatcerberus Got it! Thank you for:
Thanks to this I finally understood where the actual problem is, i.e. the type of the expression not being evaluated properly. I agree that this is essentially a duplicate of: #10727 and also #50185. |
@apendua No problem, glad I was able to communicate that. Sorry if I got too technical in spots; for all its unsoundness, TypeScript was my gateway drug into type/category theory so it's very easy for me to get carried away with theoretical explanations. |
I know this is closed but I wanted to know if anyone's found a better solution for this problem than: type MyObject = { value: number };
function modify<T extends MyObject>(a: T): T {
return {
...a,
...({value: 'abc'} as T), // this should be an error?
};
} |
Bug Report
π Search Terms
type, generic, constraint, return, safe, spread
π Version & Regression Information
This is the behavior in every version I tried, and I reviewed the FAQ for entries about generics.
β― Playground Link
Playground link with relevant code
π» Code
π Actual behavior
TS has not reported any error even though
value
is not of the right type. This must be somehow related to the use of the spread operator because if I refactor the same function as:then the error is actually detected property.
π Expected behavior
TS should detect an error in both cases as there's clearly a type violation there.
The text was updated successfully, but these errors were encountered: