Skip to content

Conversation

ahejlsberg
Copy link
Member

With this PR we properly preserve the origin of empty object literal types in intersections such that the logic that automatically infers index signatures for object literal types continues to work.

Fixes #20225.
Fixes #27044.

Copy link
Member

@weswigham weswigham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will actually have a perf impact, too - rather than, say, a single {} & string intersection type existing, we'll have a {} & string for every empty object type made (that eventually gets intersected). That's how nonempty objects work, so not surprising - just a remark that it could affect performance in some way. Probably not much, since most {} in intersections I'd guess are the {} made in the compiler and used as the base constraint/inference failure type... But everwhere someone's written T={} (which is pretty often in a lot of the react stuff I've seen), we'll now be manufacturing new intersection identities.

if (getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type)) {
includes |= TypeFlags.EmptyObject;
if (isEmptyAnonymousObjectType(type)) {
if (!(includes & TypeFlags.EmptyObject)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's never a situation where we'd need to preserve multiple different empty types... Right?

@ahejlsberg
Copy link
Member Author

I don't expect this to affect performance in any measurable way.

Regarding preservation of multiple empty object types, there are just two facts that matter for empty object types in intersections, one being whether the intersection contains any empty object types, and the other being whether any of those object types originate in an object literal type (for which we can automatically infer an index signature). We didn't track the second fact at all before. With this PR we do because we preserve the (first) actual empty object type as opposed to substituting our generic emptyObjectType. Now, technically we should track whether any (instead of the first) empty object type originated in an object literal type, but I honestly think this fix is good enough.

@weswigham
Copy link
Member

Theoretically there's also the JSLiteral and JSXAttributes object flags (which can both appear on empty object literal types from JS files and jsx attributes, respectively) that affect noImplicitAny and excess property errors, respectively.

@ahejlsberg ahejlsberg merged commit a2205ad into master Nov 10, 2018
@ahejlsberg ahejlsberg deleted the fixEmptyObjectIntersection branch November 10, 2018 08:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants