Skip to content

Fix crash: JSTypeAliasDeclaration passed to GetTypeOfDeclaration during CJS declaration emit - #4663

Merged
weswigham merged 3 commits into
mainfrom
copilot/fix-typescript-7-0-webpack-compile
Jul 21, 2026
Merged

Fix crash: JSTypeAliasDeclaration passed to GetTypeOfDeclaration during CJS declaration emit#4663
weswigham merged 3 commits into
mainfrom
copilot/fix-typescript-7-0-webpack-compile

Conversation

Copilot AI commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

When a @typedef and a module.exports.Property = value assignment share the same symbol name, TypeScript merges both into symbol.Declarations — one JSTypeAliasDeclaration (type) and one BinaryExpression (value). During declaration emit, the "first-in-wins" fallback in serializeTypeForDeclaration searched for any declaration with a non-nil Type(), which matched the JSTypeAliasDeclaration. Calling GetTypeOfDeclaration on it panicked since it only handles inferrable (value) nodes.

Repro:

// local-lib/ModuleGraphConnection.js
/** @typedef {typeof T} T */
const T = Symbol();
module.exports = class ModuleGraphConnection {};
module.exports.T = T;  // ← 'T' symbol now has both JSTypeAliasDeclaration and BinaryExpression

// repro.js
/** @typedef {import('./local-lib/ModuleGraphConnection')} ImportedType */
/** @type {ImportedType} */
module.exports = class Repro {};

tsc --allowJs --emitDeclarationOnly --declaration repro.js → panic

Changes

  • internal/checker/nodebuilderimpl.go: Guard the fallback declaration search with ast.HasInferredType(d) so only inferrable (value) declarations are candidates for GetTypeOfDeclaration, filtering out JSTypeAliasDeclaration and any other non-inferrable kinds.
  • testdata/tests/cases/compiler/jsTypedefMergedWithModuleExportProperty.ts: Regression test covering this exact pattern.

Copilot AI linked an issue Jul 16, 2026 that may be closed by this pull request
…erty

When a @typedef and a module.exports.Property = ... assignment share
the same symbol name, symbol.Declarations contains both a
JSTypeAliasDeclaration and a BinaryExpression. The first-in-wins
type annotation lookup in serializeTypeForDeclaration would find the
JSTypeAliasDeclaration (because it has a non-nil Type()), then call
GetTypeOfDeclaration on it, which panics since JSTypeAliasDeclaration
is not an inferrable node.

Fix: additionally filter the lookup to only include declarations for
which HasInferredType is true, ensuring only inferrable nodes are
passed to GetTypeOfDeclaration.

Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix TypeScript 7.0 compilation issue with webpack Fix crash: JSTypeAliasDeclaration passed to GetTypeOfDeclaration during CJS declaration emit Jul 16, 2026
Copilot AI requested a review from RyanCavanaugh July 16, 2026 23:37
@RyanCavanaugh
RyanCavanaugh requested a review from weswigham July 17, 2026 18:07
@RyanCavanaugh
RyanCavanaugh marked this pull request as ready for review July 17, 2026 18:08
Copilot AI review requested due to automatic review settings July 17, 2026 18:08

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

Prevents a CJS declaration-emit panic caused by merged type and value declarations.

Changes:

  • Restricts fallback type inference to inferrable declarations.
  • Adds regression coverage and compiler baselines.
Show a summary per file
File Description
internal/checker/nodebuilderimpl.go Filters unsafe fallback declarations.
testdata/tests/cases/compiler/jsTypedefMergedWithModuleExportProperty.ts Adds the crash regression case.
testdata/baselines/reference/compiler/jsTypedefMergedWithModuleExportProperty.types Records inferred types.
testdata/baselines/reference/compiler/jsTypedefMergedWithModuleExportProperty.symbols Records merged symbols.
testdata/baselines/reference/compiler/jsTypedefMergedWithModuleExportProperty.js Records JS and declaration output.
testdata/baselines/reference/compiler/jsTypedefMergedWithModuleExportProperty.errors.txt Records expected diagnostics.

Review details

  • Files reviewed: 6/6 changed files
  • Comments generated: 0
  • Review effort level: Medium

@weswigham weswigham left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot IMO, this is a bug in hasTypeAnnotation - likely because of it relying solely on .Type() which is overbroad - it shouldn't be returning true for typedefs or similar constructs. Fix it at the root instead of patching it just here. Use getEffectiveTypeAnnotationNode in strada as a reference (even though we don't need the JSDoc lookup parts anymore) - it bails on type aliases for this reason.

…Declaration

Per reviewer feedback, fix the issue at the root in hasTypeAnnotation rather
than patching the call site. Type alias declarations have a .Type() that is their
type definition, not a type annotation on a value - mirroring getEffectiveTypeAnnotationNode
in TypeScript which explicitly bails on isTypeAliasDeclaration. This allows the
call site in serializeTypeForDeclaration to revert to the simpler hasTypeAnnotation
predicate without needing the &&ast.HasInferredType(d) guard.

Co-authored-by: weswigham <2932786+weswigham@users.noreply.github.com>

Copilot AI commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

@copilot IMO, this is a bug in hasTypeAnnotation - likely because of it relying solely on .Type() which is overbroad - it shouldn't be returning true for typedefs or similar constructs. Fix it...

Fixed in commit fb16199. hasTypeAnnotation now explicitly excludes TypeAliasDeclaration and JSTypeAliasDeclaration, mirroring the if (isTypeAliasDeclaration(node)) return undefined bail-out in getEffectiveTypeAnnotationNode. The call site reverts to the plain hasTypeAnnotation predicate — no &&ast.HasInferredType(d) needed since the only non-value declarations that have .Type() set are the type alias kinds we now filter in the function itself.

Copilot AI requested a review from weswigham July 21, 2026 18:51
@weswigham
weswigham enabled auto-merge July 21, 2026 20:53
@weswigham
weswigham added this pull request to the merge queue Jul 21, 2026
Merged via the queue into main with commit 01cbcdd Jul 21, 2026
21 checks passed
@weswigham
weswigham deleted the copilot/fix-typescript-7-0-webpack-compile branch July 21, 2026 22:02
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.

TypeScript 7.0 Can't compile webpack

5 participants