Skip to content

Fixed types of parenthesized expressions at locations with @satisfies and @type mix #61852

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Andarist
Copy link
Contributor

@Copilot Copilot AI review requested due to automatic review settings June 12, 2025 10:51
@github-project-automation github-project-automation bot moved this to Not started in PR Backlog Jun 12, 2025
@typescript-bot typescript-bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Jun 12, 2025
@typescript-bot
Copy link
Collaborator

This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise.

1 similar comment
@typescript-bot
Copy link
Collaborator

This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise.

Comment on lines +4631 to +4637
if (
(isJSDocTypeOrSatisfiesTag(tag)) && some(result, t => {
return isJSDoc(t) ? some(t.tags, isJSDocTypeOrSatisfiesTag) : isJSDocTypeOrSatisfiesTag(t);
})
) {
return false;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the rationale is that in TS files a single node can't own both at the same time

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes how JSDoc @satisfies and @type tags are associated with parenthesized expressions by tracking previously collected tags and preventing duplicates. It also adds a helper to detect both tag types and updates tests and baselines for the new behavior.

  • Track existing JSDoc tags in getJSDocCommentsAndTags and filterOwnedJSDocTags to avoid reassigning type/satisfies tags.
  • Introduce isJSDocTypeOrSatisfiesTag helper to unify tag checks.
  • Add new test checkJsdocSatisfiesTag16.ts and update baselines across several checkJsdocSatisfiesTag cases.

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

File Description
src/compiler/utilities.ts Updated JSDoc filtering logic, added result parameter and helper function
tests/cases/conformance/jsdoc/checkJsdocSatisfiesTag16.ts New test for parenthesized expressions with @satisfies tags
tests/baselines/reference/* Updated baselines to reflect the new output and error counts
Comments suppressed due to low confidence (2)

src/compiler/utilities.ts:4613

  • [nitpick] The parameter name result is ambiguous. Consider renaming it to something more descriptive like existingTags or collectedTags to clarify its purpose.
function filterOwnedJSDocTags(hostNode: Node, comments: JSDocArray, result: (JSDoc | JSDocTag)[] | undefined) {

src/compiler/utilities.ts:4644

  • [nitpick] Consider adding a brief JSDoc comment for isJSDocTypeOrSatisfiesTag to explain what conditions it checks, improving maintainability.
function isJSDocTypeOrSatisfiesTag(tag: JSDocTag) {

@@ -23,8 +22,6 @@

/**
* @satisfies {number}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

as shown by the new tests/cases/conformance/jsdoc/checkJsdocSatisfiesTag16.ts both are still checked - but they are no longer treated as duplicates. I think this is fine but maybe @sandersn would have a different opinion

Copy link
Member

Choose a reason for hiding this comment

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

It's correct to drop the error, but the first tag shouldn't even be checked--the comment on ownsJSDocTag says that satisfies tags not on parentheses don't apply to anything. I think the real bug is that type tags shouldn't apply to the parenthesized expression in this case either, but fails because @type usage is ambiguous.

@@ -5,8 +5,8 @@
let obj = /** @satisfies {{ g(s: string): void } & Record<string, unknown>} */ ({
>obj : { f(s: string): void; } & Record<string, unknown>
> : ^^^^ ^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>({ f(s) { }, // "incorrect" implicit any on 's' g(s) { }}) : { f(s: string): void; } & Record<string, unknown>
> : ^^^^ ^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>({ f(s) { }, // "incorrect" implicit any on 's' g(s) { }}) : { f(s: any): void; g(s: string): void; }
Copy link
Contributor Author

@Andarist Andarist Jun 12, 2025

Choose a reason for hiding this comment

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

as we can see here - type of this parenthesized expression is now the same as the inner's expression, which I think is the actual desired outcome (and the actual result as implemented by microsoft/typescript-go#1157 )

@jakebailey jakebailey requested a review from sandersn June 12, 2025 16:10
@@ -74,7 +74,7 @@ const t5 = /** @satisfies {T3} */((m) => m.substring(0));
>t5 : (m: string) => string
> : ^ ^^ ^^^^^
>((m) => m.substring(0)) : (m: string) => string
> : ^ ^^ ^^^^^
Copy link
Member

Choose a reason for hiding this comment

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

Sort of interesting, given the old one showed reuse here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It makes some sense - this is now the function expression's type that is contextually-typed by the @satisfies tag and not the annotation type coming from @type. @type's content can be reused (I guess) but the expression's type is "unique" so its parts can't be reused as easily

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 don't think the problem is that no more than one tag should apply, but that @type tags shouldn't apply like a caat when they aren't actually on the parenthesized expression.

I also don't think this is worth fixing in Strada. JS support is a known difference for Corsa, and will be better but stricter in many cases.

@@ -23,8 +22,6 @@

/**
* @satisfies {number}
Copy link
Member

Choose a reason for hiding this comment

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

It's correct to drop the error, but the first tag shouldn't even be checked--the comment on ownsJSDocTag says that satisfies tags not on parentheses don't apply to anything. I think the real bug is that type tags shouldn't apply to the parenthesized expression in this case either, but fails because @type usage is ambiguous.

@github-project-automation github-project-automation bot moved this from Not started to Waiting on author in PR Backlog Jun 12, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
For Uncommitted Bug PR for untriaged, rejected, closed or missing bug
Projects
Status: Waiting on author
Development

Successfully merging this pull request may close these issues.

4 participants