-
Notifications
You must be signed in to change notification settings - Fork 13k
Fix "Cannot find name 'global'. Did you mean 'global'?" #42262
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
Conversation
As I noted in a comment on #42209 this is my first foray into the compiler so I'm not sure this is the best approach. This check could also happen inside Let me know! |
@@ -0,0 +1,3 @@ | |||
export {} | |||
declare global { const x: any } | |||
global.x // should not suggest `global` (GH#42209) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, it should probably suggest globalThis
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you miss my reply after you suggested that on the issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is valid when you do:
declare global { var x: any }
So that case should be covered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make sure we're on the same page:
Are you saying spellingSuggestionGlobal1.ts
(as written, with const x
) should produce the error message Cannot find name 'global'. Did you mean 'globalThis'?
?
If so, I disagree. Users will follow that suggestion and change global.x
to globalThis.x
, then get another error (Property 'x' does not exist on type 'typeof globalThis'.
), then be confused/frustrated and have to research why it doesn't work, then probably end up ignoring the suggestion anyway and write x
instead of globalThis.x
.
Or are you saying that in situations where x
is a known property of globalThis
and the user writes global.x
that it would be nice to say Cannot find name 'global'. Did you mean 'globalThis'?
?
If so, I agree, but unfortunately that would be tricky to implement (unless I'm missing something). I'd bet that this situation occurs rarely in the wild, so it might not be worth the complexity cost to maintain a dedicated suggestion for it. I could be wrong, though.
In any case it seems orthogonal to the bugfix in this pull request. Currently if you write something like global.Math
the error message won't suggest globalThis
, either.
Regardless, I should add a test case that uses var
in the global declaration. I'll push a commit for that soon.
// Avoid suggesting "global" if it refers to a global scope augmentation declaration. | ||
if (suggestion && suggestion.valueDeclaration && isAmbientModule(suggestion.valueDeclaration) && isGlobalScopeAugmentation(suggestion.valueDeclaration)) { | ||
suggestion = undefined; | ||
} | ||
if (suggestion) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since getSuggestedLibForNonExistentName
doesn't make sense for global
, I would just invert the predicate and move it here. Or possibly return undefined
.
Either way, I think it would be better to extract the predicate to its own variable -- that way you can probably delete the comment on the first line of the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's true that getSuggestedLibForNonExistentName
doesn't make sense for global
, but execution needs to fall through to the else
case on line 2049/2053 in order to get any error message at all.
I don't like overwriting suggestion
in-place either, though. Maybe it'd be better to duplicate the error
call up here?
const isGlobalScopeAugmentationDeclaration = suggestion && suggestion.valueDeclaration && isAmbientModule(suggestion.valueDeclaration) && isGlobalScopeAugmentation(suggestion.valueDeclaration);
if (isGlobalScopeAugmentationDeclaration) {
if (nameArg) {
error(errorLocation, nameNotFoundMessage, diagnosticName(nameArg));
}
}
else if (suggestion) {
// ...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ooh, I forgot that there weren't any other error
calls afterward. I guess it's better to keep it the way it is.
@@ -2028,6 +2028,10 @@ namespace ts { | |||
let suggestion: Symbol | undefined; | |||
if (suggestedNameNotFoundMessage && suggestionCount < maximumSuggestionCount) { | |||
suggestion = getSuggestedSymbolForNonexistentSymbol(originalLocation, name, meaning); | |||
const isGlobalScopeAugmentationDeclaration = suggestion && suggestion.valueDeclaration && isAmbientModule(suggestion.valueDeclaration) && isGlobalScopeAugmentation(suggestion.valueDeclaration); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In hindsight I wish I'd named this suggestionIs...
, but the name is already obnoxiously long.
Maybe suggestionIsGlobalDeclaration
? suggestionIsGlobalModule
? Something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in context, I think this is a pretty good name.
@@ -2028,6 +2028,10 @@ namespace ts { | |||
let suggestion: Symbol | undefined; | |||
if (suggestedNameNotFoundMessage && suggestionCount < maximumSuggestionCount) { | |||
suggestion = getSuggestedSymbolForNonexistentSymbol(originalLocation, name, meaning); | |||
const isGlobalScopeAugmentationDeclaration = suggestion && suggestion.valueDeclaration && isAmbientModule(suggestion.valueDeclaration) && isGlobalScopeAugmentation(suggestion.valueDeclaration); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in context, I think this is a pretty good name.
// Avoid suggesting "global" if it refers to a global scope augmentation declaration. | ||
if (suggestion && suggestion.valueDeclaration && isAmbientModule(suggestion.valueDeclaration) && isGlobalScopeAugmentation(suggestion.valueDeclaration)) { | ||
suggestion = undefined; | ||
} | ||
if (suggestion) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ooh, I forgot that there weren't any other error
calls afterward. I guess it's better to keep it the way it is.
Avoid suggesting the
global
keyword (from global scope augmentation declarations) as typo fix when resolving names.Fixes #42209.