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

Get return type from @type tag #25580

Merged
merged 4 commits into from
Jul 12, 2018
Merged

Get return type from @type tag #25580

merged 4 commits into from
Jul 12, 2018

Conversation

sandersn
Copy link
Member

This only happens in the checker, where the type is easily accessible. The syntax-based check in getEffectiveReturnTypeNode remains as a fast path, and for other uses that can't make a call to getTypeFromTypeNode.

Fixes #25525

This only happens in the checker, where the type is easily accessible.
The syntax-based check in getEffectiveReturnTypeNode as a fast path, and
for other uses that don't want to make a call to getTypeFromTypeNode.

Fixes #25525
@sandersn sandersn requested a review from a user July 11, 2018 16:32
if (nodeIsMissing((<FunctionLikeDeclaration>declaration).body)) {
return anyType;
}
}

function getReturnTypeOfTypeTag(node: Node) {
Copy link

Choose a reason for hiding this comment

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

Think this would be neater with node: SignatureDeclaration | JSDocSignature

@@ -20521,23 +20536,28 @@ namespace ts {
return type;
}

function getReturnOrPromisedType(node: ArrowFunction | FunctionExpression | FunctionDeclaration | MethodDeclaration | MethodSignature, functionFlags: FunctionFlags) {
Copy link

Choose a reason for hiding this comment

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

Could be node: FunctionLikeDeclaration | MethodSignature

}

/** @type {2 | 3} - overloads are not supported, so there will be an error */
var twothree = monaLisa(false);
Copy link

Choose a reason for hiding this comment

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

The error here doesn't say anything about overloads through. (error TS2322: Type '1 | 2' is not assignable to type '2 | 3'.) The inferred return type of the function 1 | 2 is used, but it really shouldn't if there was an explicit type annotation. If the function returned any, there would be silent failure here, even though it had an explicit type annotation.

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right, it's only an error because we go back to ignoring the type annotation. The correct thing is to treat a type annotation with multiple signatures as an overload set and use the normal typescript rules for checking that the implementation signature is assignable to the overload set.

But the JS implementation isn't typed, so that check doesn't really make sense. Basically, I left it the way it was because I couldn't think of any useful checking.

Copy link
Member Author

Choose a reason for hiding this comment

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

After discussing this in person, here's what we decided

  1. /** @type {number} */ should error. It doesn't today, but I think it's clearly wrong enough to deserve an error.
  2. /** @type {Gioconda} */ should give monaLisa an overload type, and the function parameters and return type should be checked according to the typescript overload rules. This will usually succeed since the parameters will be any, and the return type will therefore usually be any. But it will give the desired overload type to callers of the function, which is why somebody would write this type in the first place.
  3. (2) is not just a simple fix so I will leave the current silent-fallback behaviour in this PR and open an issue to track it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Opened #25590 to track (2).

if (nodeIsMissing((<FunctionLikeDeclaration>declaration).body)) {
return anyType;
}
}

function getReturnTypeOfTypeTag(node: Node) {
if (isInJavaScriptFile(node)) {
Copy link

Choose a reason for hiding this comment

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

Opinons may vary but I tend to prefer to be flatter when lots of sequential tests are involved:

const typeTag = isInJavaScriptFile(node) ? getJSDocTypeTag(node) : undefined;
const signatures = typeTag && typeTag.typeExpression && getSignaturesOfType(getTypeFromTypeNode(typeTag.typeExpression), SignatureKind.Call);
return signatures && signatures.length === 1 ? getReturnTypeOfSignature(signatures[0]) : undefined;

@@ -20521,23 +20536,28 @@ namespace ts {
return type;
}

function getReturnOrPromisedType(node: ArrowFunction | FunctionExpression | FunctionDeclaration | MethodDeclaration | MethodSignature, functionFlags: FunctionFlags) {
const returnTypeNode = getEffectiveReturnTypeNode(node);
Copy link

Choose a reason for hiding this comment

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

This is only used if (functionFlags & FunctionFlags.AsyncGenerator) !== FunctionFlags.Async, could it be computed only then?

Copy link
Member Author

Choose a reason for hiding this comment

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

checkAsyncFunctionReturnType immediately calls getEffectiveReturnTypeNode, and assumes that its result is defined, so it implicitly used it. I added a parameter returnTypeNode to make the dependency explicit (and get rid of yet another TODO #18217)

@sandersn
Copy link
Member Author

I added a separate error for when the type tag isn't callable. It ended up separate from getReturnTypeOfTypeTag because reporting the error in checkFunctionOrMethodDeclaration is the right place.

@sandersn sandersn merged commit bd7b97c into master Jul 12, 2018
@mhegazy mhegazy deleted the jsdoc/return-type-of-type-tag branch July 12, 2018 17:50
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.

1 participant