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

Fix issue #22923 #23050

Merged
merged 1 commit into from
Apr 6, 2018
Merged

Fix issue #22923 #23050

merged 1 commit into from
Apr 6, 2018

Conversation

akhomchenko
Copy link
Contributor

@akhomchenko akhomchenko commented Apr 1, 2018

Fixes #22923

I'm still not sure that isPromiseLike should use isReferenceToType or something more smart (e.g. getPromisedTypeOfPromise to resolve actual types)

@akhomchenko akhomchenko force-pushed the fix/22923 branch 2 times, most recently from d789ce0 to 49a2599 Compare April 1, 2018 20:20
@@ -16409,6 +16409,9 @@ namespace ts {
if (suggestion !== undefined) {
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestion);
}
else if (isPromiseLike(containingType)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

call getPromisedTypeOfPromise instead. this will return you the type of the T in Promise<T>. this should handle unions and custom promises, etc.. if it is undefined then it was not a promise.

you also need to check if the property exists on the promisedType. in other words:

var p: Pomise<number>;
p.toExponential;  // should report error `Property toExponential does not exist on type 'Promise<number>' did you forget `await`?`

var x: Promise<string>;
p.toExponential;  // should not report the `did you forget await` part.

@akhomchenko
Copy link
Contributor Author

akhomchenko commented Apr 2, 2018

So, I've fixed a check plus have dropped tests for Union and Intersection and closed #23058. Should I add any extra tests?

@@ -2000,7 +2000,10 @@
"category": "Error",
"code": 2569
},

"Property '{0}' does not exist on type '{1}'. Did you forget to await the '{1}'?": {
Copy link
Contributor

Choose a reason for hiding this comment

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

how about Property '{0}' does not exist on type '{1}'. Did you forget 'await' ?

Copy link
Contributor

Choose a reason for hiding this comment

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

@DanielRosenwasser can i get your input on this error message as well.

Copy link
Member

Choose a reason for hiding this comment

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

Property '{0}' does not exist on type '{1}'. Did you forget to use 'await'? is probably the best one actually.

Copy link
Member

Choose a reason for hiding this comment

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

Or potentially

Property '{0}' does not exist on type '{1}', but does exist on type '{2}'. Did you forget to use 'await'?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had this at #23058. So which message?

  • Property '{0}' does not exist on type '{1}'. Did you forget to use 'await'?
  • Property '{0}' does not exist on type '{1}', but does exist on type '{2}'. Did you forget to use 'await'?

if (suggestion !== undefined) {
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestion);
}
else if (promisedType && getPropertyOfType(promisedType, propNode.escapedText)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit, consider moving const promisedType = getPromisedTypeOfPromise(containingType); inside an else block for if (suggestion !== undefined). it just makes sure we only compute it if we need it.

Copy link
Member

@DanielRosenwasser DanielRosenwasser left a comment

Choose a reason for hiding this comment

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

Close to perfect. Can you also add the following to your tests?

  • try accessing a string property on string | Promise<string>
  • use an element access to access a property on the awaited type.

@@ -16410,7 +16410,13 @@ namespace ts {
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestion);
}
else {
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
const promisedType = getPromisedTypeOfPromise(containingType);
Copy link
Member

Choose a reason for hiding this comment

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

I would say that you should do the promise check before any sort of spelling checks because if a property exists on the awaited type, that's almost always a preferable suggestion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do

@akhomchenko
Copy link
Contributor Author

akhomchenko commented Apr 4, 2018

try accessing a string property on string | Promise

this is clear

use an element access to access a property on the awaited type.

What do you mean by element access? Something like foo.bar?

@mhegazy
Copy link
Contributor

mhegazy commented Apr 4, 2018

element access is a[expression], property access is a.name

@akhomchenko
Copy link
Contributor Author

akhomchenko commented Apr 5, 2018

Ok, I've updated a message and have added the case for string | Promise<string>. Latest results in:

!!! error TS2339: Property 'toLowerCase' does not exist on type 'string | Promise<string>'.
!!! error TS2339:   Property 'toLowerCase' does not exist on type 'Promise<string>'.

As for element access I can not get what should I test. E.g.

function f(x: Promise<string>) {
    return x["toString"]();
}

will not emit even an old error, as they are in different branches - checkPropertyAccessExpression and checkIndexedAccess. No?

Or do you mean something like this?

function f(x: Promise<string>, y: any) {
    return y[x.toString()];
}

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Apr 6, 2018

I meant something like x["toLowerCase"]() which should use the same error handling branch if I'm not mistaken.

@mhegazy
Copy link
Contributor

mhegazy commented Apr 6, 2018

I meant something like x"toLowerCase" which should use the same error handling branch if I'm not mistaken

there is no error here for using a property that does not exist. the only error is under --noImplicitAny. so do not think this is an issue.

@mhegazy mhegazy merged commit da31239 into microsoft:master Apr 6, 2018
@mhegazy
Copy link
Contributor

mhegazy commented Apr 6, 2018

thanks @gagoman!

@akhomchenko
Copy link
Contributor Author

Yes, I've tested this case. It is not covered by this branch.

@akhomchenko akhomchenko deleted the fix/22923 branch April 6, 2018 16:40
@microsoft microsoft locked and limited conversation to collaborators Jul 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Check if element types of Promises contain a property when issuing a missing property error
3 participants