Skip to content

fix(64058): fix reparse jsdoc @extends type arguments for call expressions - #64072

Merged
Jake Bailey (jakebailey) merged 2 commits into
microsoft:mainfrom
a-tarasyuk:fix/64058
Oct 14, 2026
Merged

Jake Bailey (jakebailey) merged 2 commits into
microsoft:mainfrom
a-tarasyuk:fix/64058

Conversation

@a-tarasyuk

@a-tarasyuk Oleksandr Tarasiuk (a-tarasyuk) commented Aug 28, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #64058

Copilot AI balanced review requested due to automatic review settings August 28, 2026 08:01
@github-project-automation github-project-automation Bot moved this to Not started in PR Backlog Aug 28, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes JSDoc @extends type arguments for call-expression heritage clauses.

Changes:

  • Copies JSDoc type arguments onto the parsed heritage node.
  • Adds parser and compiler regression coverage.
  • Removes the previous property-access matching helper.

Reviewed changes

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

Show a summary per file
File Description
tsc/internal/parser/reparser.go Reparses @extends type arguments.
tsc/internal/ast/utilities.go Removes the old name-matching helper.
tsc/internal/parser/parser_test.go Tests reparsed AST linkage.
tsc/testdata/tests/cases/conformance/jsdoc/extendsTag7.ts Adds the compiler regression case.
tsc/testdata/baselines/reference/conformance/extendsTag7.types Records inferred types.
tsc/testdata/baselines/reference/conformance/extendsTag7.symbols Records resolved symbols.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread tsc/internal/parser/reparser.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Comment thread tsc/internal/ast/utilities.go Outdated
Comment thread tsc/internal/parser/reparser.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The effective-base symbol gate rejects valid call-expression @extends cases and produces incorrect types and diagnostics.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 30/30 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread tsc/internal/checker/jsdoc.go Outdated
@jakebailey

Copy link
Copy Markdown
Member

Sorry, after thinking about it I'm flip flopping... Your Aug 29 version (a315a46) was right. Copying the type arguments onto the call means the same thing as the TS extends A.extend()<string>. My mixin(A) worry would just produce the same error TS reports for that code.

Could you go back to it with two tweaks?

  1. Apply the arguments to any heritage expression that isn't a plain or dotted name (IsEntityNameExpression), not only to calls.
  2. For the mismatch check, use assignability (base type assignable to the tag's type) instead of comparing symbols, since a mixin's result has no single symbol, so e.g. @extends {Other<string>} on mixin(A) slips through.

Here's a test covering those; only MismatchedMixin should error:

// @target: esnext
// @allowJs: true
// @checkJs: true
// @strict: true
// @noEmit: true

// @filename: a.js
/** @template T */
class A {
    /** @param {T} value */
    constructor(value) {
        this.value = value;
    }
}

/**
 * @template T
 * @extends {A<T>}
 */
class Sub extends A {
    /** @returns {typeof Sub} */
    static extend() {
        return this;
    }
}

/** @template T */
class Other {
    /** @param {T} other */
    constructor(other) {
        this.other = other;
    }
}

/**
 * @template {new (...args: any[]) => any} C
 * @param {C} Base
 */
function mixin(Base) {
    return class extends Base {
        extra = 1;
    };
}

const ns = { A };
/** @type {boolean} */
let cond = true;

/** @extends {A<string>} */
class ViaMixin extends mixin(A) {}
/** @type {string} */
const viaMixin = new ViaMixin("ok").value;
/** @type {number} */
const viaMixinExtra = new ViaMixin("ok").extra;

/** @extends {Other<string>} */
class MismatchedMixin extends mixin(A) {}

/** @extends {A<string>} */
class ViaSubclass extends Sub.extend() {}
/** @type {string} */
const viaSubclass = new ViaSubclass("ok").value;

/** @extends {A<string>} */
class ViaElementAccess extends ns["A"] {}
/** @type {string} */
const viaElementAccess = new ViaElementAccess("ok").value;

/** @extends {A<string>} */
class ViaConditional extends (cond ? A : A) {}
/** @type {string} */
const viaConditional = new ViaConditional("ok").value;

Thanks for bearing with me!

@jakebailey

Copy link
Copy Markdown
Member

Looks great, thanks! One thing: extends null now gets the arguments too, so /** @extends {A<string>} */ class B extends null {} emits extends null<string> in the .d.ts. Could you skip KindNullKeyword in the reparser and add a test for it?

@github-project-automation github-project-automation Bot moved this from Not started to Needs merge in PR Backlog Oct 14, 2026
@jakebailey
Jake Bailey (jakebailey) added this pull request to the merge queue Oct 14, 2026
Merged via the queue into microsoft:main with commit f5cdce9 Oct 14, 2026
29 checks passed
@github-project-automation github-project-automation Bot moved this from Needs merge to Done in PR Backlog Oct 14, 2026
NullVoxPopuli added a commit to NullVoxPopuli/ember-content-mapper that referenced this pull request Oct 15, 2026
This nightly includes microsoft/TypeScript#64072 (the #64058 fix). It
applies the JSDoc @extends type arguments to the call's return type, so
over Component.extend(Evented), which returns a constructor that is not
generic, the error changes to TS2508 and the signature is still lost.
Update the upstream-differences snapshot and docs to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For Backlog Bug PRs that fix a backlog bug

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

TS7: @extends is ignored when the heritage is a call expression (Base.extend())

3 participants