Skip to content

Make direct assignments to cjs exports considered literal contexts #39816

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

Merged
merged 5 commits into from
Mar 9, 2022

Conversation

weswigham
Copy link
Member

@weswigham weswigham commented Jul 29, 2020

Fixes #37403
Fixes #37404

@weswigham weswigham requested a review from sandersn July 29, 2020 19:52
@typescript-bot typescript-bot added Author: Team For Milestone Bug PRs that fix a bug with a specific milestone For Backlog Bug PRs that fix a backlog bug labels Jul 29, 2020
@weswigham weswigham added the Breaking Change Would introduce errors in existing code label Jul 29, 2020
Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

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

I agree with this if we already issue an error for

module.exports.a = 1
module.exports.a = 2

Although I didn't think we did. It's a little weird that I don't see any new error baselines, so maybe we just don't have coverage.

Besides that, I have a couple of questions and a few formatting suggestions.

@@ -8069,7 +8069,8 @@ namespace ts {
if (containsSameNamedThisProperty(expression.left, expression.right)) {
return anyType;
}
const type = resolvedSymbol ? getTypeOfSymbol(resolvedSymbol) : getWidenedLiteralType(checkExpressionCached(expression.right));
const isDirectExport = kind === AssignmentDeclarationKind.ExportsProperty && (isPropertyAccessExpression(expression.left) || isElementAccessExpression(expression.left)) && (isModuleExportsAccessExpression(expression.left.expression) || (isIdentifier(expression.left.expression) && isExportsIdentifier(expression.left.expression)));
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
const isDirectExport = kind === AssignmentDeclarationKind.ExportsProperty && (isPropertyAccessExpression(expression.left) || isElementAccessExpression(expression.left)) && (isModuleExportsAccessExpression(expression.left.expression) || (isIdentifier(expression.left.expression) && isExportsIdentifier(expression.left.expression)));
const isDirectExport = kind === AssignmentDeclarationKind.ExportsProperty
&& isAccessExpression(expression.left)
&& (isModuleExportsAccessExpression(expression.left.expression) || (isIdentifier(expression.left.expression) && isExportsIdentifier(expression.left.expression)));

I think there might be an existing utility that does what you want here, but it may include other cases. (Could it be isCommonJsExportPropertyAssignment?)

Copy link
Member Author

Choose a reason for hiding this comment

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

I couldn't find one. :S

Copy link
Member

@sandersn sandersn Jul 31, 2020

Choose a reason for hiding this comment

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

It would still be nice to (1) switch to isAccessExpression (2) break up this super-long line

@weswigham
Copy link
Member Author

I agree with this if we already issue an error for

We do! I was surprised we did as well! But given that, considering the exports as psuedo-readonly makes sense to me.

@weswigham
Copy link
Member Author

@typescript-bot user test this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jul 31, 2020

Heya @weswigham, I've started to run the parallelized community code test suite on this PR at 380990f. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master.

@weswigham
Copy link
Member Author

Diff from master's user baselines is just a commit sha, so it looks fine~

@weswigham
Copy link
Member Author

Lemme fix that lint error...

@weswigham weswigham requested a review from sandersn July 31, 2020 19:03
Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

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

As I said during the design meeting, I think if there aren't many breaking changes in the user tests, you should just merge after we've cut 4.0 RC.

@@ -8069,7 +8069,8 @@ namespace ts {
if (containsSameNamedThisProperty(expression.left, expression.right)) {
return anyType;
}
const type = resolvedSymbol ? getTypeOfSymbol(resolvedSymbol) : getWidenedLiteralType(checkExpressionCached(expression.right));
const isDirectExport = kind === AssignmentDeclarationKind.ExportsProperty && (isPropertyAccessExpression(expression.left) || isElementAccessExpression(expression.left)) && (isModuleExportsAccessExpression(expression.left.expression) || (isIdentifier(expression.left.expression) && isExportsIdentifier(expression.left.expression)));
Copy link
Member

@sandersn sandersn Jul 31, 2020

Choose a reason for hiding this comment

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

It would still be nice to (1) switch to isAccessExpression (2) break up this super-long line

const isDirectExport = kind === AssignmentDeclarationKind.ExportsProperty && (isPropertyAccessExpression(expression.left) || isElementAccessExpression(expression.left)) && (isModuleExportsAccessExpression(expression.left.expression) || (isIdentifier(expression.left.expression) && isExportsIdentifier(expression.left.expression)));
const type = resolvedSymbol ? getTypeOfSymbol(resolvedSymbol)
: isDirectExport ? getRegularTypeOfLiteralType(checkExpressionCached(expression.right))
: getWidenedLiteralType(checkExpressionCached(expression.right));
if (type.flags & TypeFlags.Object &&
Copy link
Member

Choose a reason for hiding this comment

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

If we change how js file works we probably want to change how json works too. As we say that json is nothing but module.exports = json but with json it is questionable if we really need to use literal type or not.

@sandersn
Copy link
Member

sandersn commented Sep 3, 2020

@weswigham what do you think about @sheetalkamat's point about JSON? I think that's the only thing blocking this from being merged.

@weswigham
Copy link
Member Author

@weswigham what do you think about @sheetalkamat's point about JSON? I think that's the only thing blocking this from being merged.

I'd rather not change the literaliness of json at only the top level (also it's an export assignment, not an assignment of an individual export, so it's a bit different in structure) since we have ongoing discussions about as const on a json import and the like (which would be much more complete).

@sandersn
Copy link
Member

@sheetalkamat does that make sense to you? If so, can you sign off?

@sheetalkamat
Copy link
Member

I think @DanielRosenwasser should comment on this or potentially discuss this in design meeting to ensure we are all on same page. I am not sure why export.j =1 in js file should be different from export = { j : 1} in the json file
On the other hand the repro from the issue this tries to fix atleast somewhat makes sense why the const x = 10; export.x = x should not be widened but i dont think scneario export.x = 1 makes it similar which is similar to json file in my opinion

@sandersn
Copy link
Member

@DanielRosenwasser can you give an opinion on @sheetalkamat 's question?

@DanielRosenwasser
Copy link
Member

It sounds like this might be fixed as per #37403 (comment)

@ExE-Boss
Copy link
Contributor

ExE-Boss commented Mar 11, 2021

Actually, #37404 is still broken, and #37403 was only partially fixed, so this is still needed.

@weswigham
Copy link
Member Author

Yeah, I can't actually guide/update a thing right now, soo.... would need help from y'all 🤷

@sandersn
Copy link
Member

Re-reading this, I vote that we take this change and then discuss a change to JSON literalness separately. I think this is a good change on its own and the mismatch with JSON won't be too noticeable.

@sheetalkamat is that OK with you?
If so, @weswigham, can you bring this back to date with master?

@RyanCavanaugh RyanCavanaugh removed this from the TypeScript 4.3.0 milestone Aug 5, 2021
@weswigham
Copy link
Member Author

@sandersn been awhile, but think we wanna merge this now?

@weswigham weswigham merged commit 3f63804 into microsoft:main Mar 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team Breaking Change Would introduce errors in existing code For Backlog Bug PRs that fix a backlog bug For Milestone Bug PRs that fix a bug with a specific milestone
Projects
Archived in project
7 participants