-
Notifications
You must be signed in to change notification settings - Fork 13.1k
JSDoc @type tag optional parameters #48132
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
|
This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise. |
sandersn
left a comment
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.
I think this basic approach is good enough, although it would be slightly more accurate to copy over the properties from signature to a fresh signature whose symbol is the function value instead of the @type annotation.
Why are there so many deleted baseline files? After that I think this will be ready to merge.
| ~~~ | ||
| !!! error TS2554: Expected 1 arguments, but got 0. | ||
| !!! related TS6210 tests/cases/conformance/jsdoc/a.js:5:12: An argument for 's' was not provided. | ||
| !!! related TS6210 tests/cases/conformance/jsdoc/a.js:4:13: An argument for 's' was not provided. |
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.
This error span change shows that re-using the signature isn't precisely correct. It's probably close enough, though, and it would take much more code to copy over the properties of the declared signature to the new signature.
|
This seems okay to fix the bug, but I'm not sure exactly if the changes in the diff are "good" or not. It seems like what's happening is that the declared parameter name (in the JS) is getting totally overridden by the jsdoc in the symbols output, which feels odd. I'm not sure what practical effect is has, though. |
111a593 to
7b85698
Compare
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.
@jakebailey Thanks for reviewing!
- I rebased, which eliminated the unrelated, deleted baselines (they were for tests that no longer exist).
src/compiler/checker.ts
Outdated
| } | ||
|
|
||
| function getSignatureFromDeclaration(declaration: SignatureDeclaration | JSDocSignature): Signature { | ||
| if (isInJSFile(declaration)) { |
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.
I noticed getSignatureOfTypeTag() already calls isInJSFile(), so I dropped that condition from this change, and from the other getSignatureOfTypeTag()/getParameterTypeOfTypeTag() call sites. It's a cosmetic change I'm happy to skip though, if you prefer?
| var noreturn = obj => void obj.title | ||
| >noreturn : NoReturn | ||
| >obj => void obj.title : (obj: { e: number; m: number; title: string; }) => any | ||
| >obj => void obj.title : (s: { e: number; m: number; title: string; }) => any |
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.
These .types baselines are okay and expected, I think? We're now obeying the @type tag, so the output is, e.g. the NoReturn type, and the NoReturn parameter name is s.
5645d0d to
eab90ca
Compare
5dd9a1b to
f12b97f
Compare
|
I noticed that there's currently an error if an initializer isn't compatible with it's target, and that this PR was suppressing that, by applying
⏯️ Playground link🧑💻 Code// @checkJs
// @filename: input.js
// @errors: 2322 8030
// Confirm initializers are compatible.
// They can't have more parameters than the target.
/** @type {() => void} */
function func(more) {}
/** @type {() => void} */
const variable = function (more) {};
/** @type {() => void} */
const arrow = (more) => {};
({
/** @type {() => void} */
method(more) {},
/** @type {() => void} */
prop: function (more) {},
/** @type {() => void} */
arrow: (more) => {},
});📓 TILSome notes from exploring the code (not necessarily of benefit to anyone but myself):
|
efb13ef to
5bb7079
Compare
|
Is this ready to review again? |
|
@sandersn Yes please. |
sandersn
left a comment
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.
Looks good except for a couple of comment suggestions.
src/compiler/checker.ts
Outdated
| } | ||
| } | ||
| result.push(getSignatureFromDeclaration(decl)); | ||
| // If this is a function or method declaration, get the accurate minArgumentCount from the @type tag, if present. |
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.
| // If this is a function or method declaration, get the accurate minArgumentCount from the @type tag, if present. | |
| // If this is a function or method declaration, get the signature from the @type tag, if present. |
src/compiler/checker.ts
Outdated
| // If this is a variable or property declaration, apply the @type tag to it | ||
| // (getTypeForVariableLikeDeclaration()), not to the initializer. |
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.
I would delete this. I tried rewording and I got
| // If this is a variable or property declaration, apply the @type tag to it | |
| // (getTypeForVariableLikeDeclaration()), not to the initializer. | |
| // other kinds are handled through contextual typing |
which is OK, but not that valuable to state explicitly. I'll leave it up to you whether you want to keep this, since I'm probably over-familiar with the code.
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.
@sandersn Thanks! I agree, as written the whole comment isn't that valuable ... I guess I was aiming to answer:
- Q: Why are we doing this for function and method declarations?
A: For optional parameters. - Q: Why are we excluding contextually-typed kinds?
A: Because they're already handled elsewhere, and not excluding them would suppress compatibility checks.
I've added a commit with an alternative rewording (based on your suggestions), but I'm very open to going with your preference!
sandersn
left a comment
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.
Sorry I missed this until now. It's late enough in the 4.8 beta that I want to hold this for 4.9, so I'll merge it next week.
TS obeys JSDoc
@typetag signatures, but not parameter optionality. Projects work around this by adding| voidto parameters in@typetags, but this isn't strictly correct, and leads to problems later using those values, withoutExclude<param, void>. e.g.🧐 Investigation
The signatures passed to
resolveCall()ignore@typetags entirely, so they have the wrongminArgumentCount, sohasCorrectArity()fails. I think they obey@paramtags?Otherwise, the applicability checks obey
@typetags, becausegetSignatureApplicabilityError()callsgetTypeAtPosition(), which ... callsgetTypeForVariableLikeDeclaration(), which contains:since #26694 (or #22692?).
Backing up,
resolveCallExpression()callsresolveCall()oncallSignaturesreturned bygetSignaturesOfType()(with the wrongminArgumentCount).getSignaturesOfType()calls ...getSignatureFromDeclaration(), which obeys@paramtags, but not@typetags?So maybe the solution is to (roughly) copy the
@typetag logic fromgetTypeForVariableLikeDeclaration()->getSignatureFromDeclaration()? That's what I've tried to do in this PR.🔍 Search terms
jsdoc type tag optional parameters signature arity
🕗 Version & regression information
2.8.0-dev.20180320 - 4.7.0-dev.20220305
⏯️ Playground link
Workbench repro
🧑💻 Code
🙁 Actual behavior
🙂 Expected behavior
With this PR: