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

Wrong types inferred and false-positive ts(2783) when spreading object literals with "inline" __proto__ #45580

Closed
worstpractice opened this issue Aug 26, 2021 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@worstpractice
Copy link

worstpractice commented Aug 26, 2021

Bug Report

Hello everyone, first time issue reporter here ヾ(•ω•`)o Thank you so much in advance for all the great work ♥

Related: #38385, #42359

The notes that follow are based on this playground.

NOTE: None of the flags I have set in that link matter or influence the result, they are simply some flags I like.

Please note that all the properties involved in this example are (AFAIK) statically known (to the extent reasonably possible, including as const for objects). Even so, the wrong types are inferred.

The bug

One compiler error (2783) and one explainer/hint message appear when hovering over the single squiggly line.

  1. 'proto' is specified more than once, so this usage will be overwritten.(2783)

  2. This spread always overwrites this property.

Both are in fact wrong (in this special case, specifically involving __proto__ in object literals).

To the best of my knowledge, spreading could never overwrite a __proto__ declared "inline" (in the same object literal), irrespective (!) of ordering.

Put another way: no matter where (in the object literal) __proto__ appears — if it's there at all, it "wins" automatically.

Furthermore, hovering over protoFollowedBySpread reveals its inferred type to be:

{ readonly __proto__: null; }

...which is incorrect. The actual __proto__ is Array.prototype, which is why console.log('map' in protoFollowedBySpread) logs true at runtime.

Considering the broken type inference, I would wager to guess that the type checker is (as of yet) uneducated on the particular semantics at play in this somewhat rare (though well-defined) corner case of the language.

🔎 Search Terms

  • proto
  • spread
  • object literal
  • ts(2783)
  • specified more than once
  • will be overwritten

🕗 Version & Regression Information

This was the behavior I observed in every version I tried.

⏯ Playground Link

Playground link with relevant code

💻 Code

export const foo = {
  __proto__: null,
} as const;

export const protoFollowedBySpread = {
  __proto__: Array.prototype, // This error is itself erroneous (in this one special case, specifically involving `__proto__` in object literals).
  ...foo,
} as const;

export const spreadFollowedByProto = {
  ...foo,
  __proto__: Array.prototype, // No error is reported when the "inline" `__proto__` comes AFTER `...foo`. No surprises here. ;
} as const; 

console.log('map' in protoFollowedBySpread); // logs `true`(the inferred type is wrong)

🙁 Actual behavior

Please see the playground. In short:

  • Invalid type inference
  • False positive ts(2783)
  • Hint that (while a wonderful and friendly feature) happens to mislead in this particular case

🙂 Expected behavior

Simply put, a correct understanding of the language semantics in this case. Notable mentions here would be (two sides of the same coin):

  • No errors reported where nothing is wrong
  • Correctly inferring the type based on the (AFAIK) statically known properties involved
@andrewbranch andrewbranch added Bug A bug in TypeScript and removed Bug A bug in TypeScript labels Aug 26, 2021
@andrewbranch
Copy link
Member

You are right, but this doesn’t seem like it needs to be a separate issue from #38385. We wouldn’t have any business understanding that __proto__ is special in a spread without understanding the other ways in which __proto__ is special. Maybe you’d like to comment on the related issue or PR instead to ensure this test case is covered?

@andrewbranch andrewbranch added the Duplicate An existing issue was already created label Aug 26, 2021
@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants