Skip to content

Retain uninitialized binding patterns for variable declarations in declaration emit - #4775

Open
weswigham wants to merge 2 commits into
microsoft:mainfrom
weswigham:type-nodes-for-binding-patterns
Open

Retain uninitialized binding patterns for variable declarations in declaration emit#4775
weswigham wants to merge 2 commits into
microsoft:mainfrom
weswigham:type-nodes-for-binding-patterns

Conversation

@weswigham

@weswigham weswigham commented Jul 28, 2026

Copy link
Copy Markdown
Member

Fixes #4525

As a side-effect, this makes exported binding patterns (potentially) isolatedDeclarations-emittable, since we can lookup their local type node/assertion/inference result the same as any other variable declaration.

Honestly, we've supported binding patterns in declaration files for... as long as I can remember, at least (and we've emitted them in parameter positions for many many major releases at this point), so I don't think there's really any harm in this - unless you'd get mad that when you write export const [,...rest] = [first(), ...others()] we now expose the type of first() in the declaration file even though it's not actually an accessible part of the exported shape. Still - that's probably worthwhile in exchange for making binding patterns isolatedDeclarations-emittable.

t = b.ch.instantiateType(b.ch.getWriteTypeOfSymbol(symbol), b.ctx.mapper)
} else if symbol != nil && (symbol.Flags&(ast.SymbolFlagsTypeLiteral|ast.SymbolFlagsSignature) == 0) {
t = b.ch.instantiateType(b.ch.getWidenedLiteralType(b.ch.getTypeOfSymbol(symbol)), b.ctx.mapper)
if symbol == nil {

@weswigham weswigham Jul 28, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The "interesting" part implementation-wise is that variable declarations hosting binding patterns do have an overall type (ofc they do), but don't have a symbol bound to them (only the individual names in the binding pattern do). Somehow, this is the first time we've needed to serialize such symbol-less declarations, so I had to adjust the pipeline to actually handle nil symbols.

(Compare with parameters where even the nameless binding pattern parameters get a bound symbol that refers to them, since that's how the argument type is looked up externally.)

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

Preserves variable binding patterns in declaration emit and updates type lookup to support symbol-less declarations.

Changes:

  • Emits destructuring patterns rather than flattened declarations.
  • Adds regression coverage and updates affected baselines.
  • Handles symbol-less declaration type resolution safely.

Reviewed changes

Copilot reviewed 50 out of 50 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
testdata/tests/cases/compiler/declarationEmitVariableBindingPatternsRetained.ts Adds regression coverage.
testdata/submoduleAccepted.txt Registers accepted baseline differences.
testdata/baselines/reference/submoduleAccepted/conformance/stringLiteralTypesAndTuples01.js.diff Accepts tuple-pattern emit.
testdata/baselines/reference/submoduleAccepted/conformance/dependentDestructuredVariables.js.diff Accepts object-pattern emit.
testdata/baselines/reference/submoduleAccepted/compiler/isolatedDeclarationErrorsExpressions.errors.txt.diff Accepts isolated-declaration diagnostics.
testdata/baselines/reference/submoduleAccepted/compiler/destructuredDeclarationEmit.js.diff Accepts nested-pattern emit.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitRetainsJsdocyComments.js.diff Updates comment-preserving emit.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitOptionalMappedTypePropertyNoStrictNullChecks3.js.diff Accepts mapped-type pattern emit.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitOptionalMappedTypePropertyNoStrictNullChecks2.js.diff Accepts mapped-type pattern emit.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitOptionalMappedTypePropertyNoStrictNullChecks1.js.diff Accepts mapped-type pattern emit.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitNonExportedBindingPattern.js.diff Accepts non-exported patterns.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitExpressionInExtends6.js.diff Updates destructured class dependency emit.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitDestructuringPrivacyError.js.diff Updates privacy-case emit.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitDestructuringObjectLiteralPattern2.js.diff Accepts nested object patterns.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitDestructuringObjectLiteralPattern1.js.diff Accepts object patterns.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitDestructuringObjectLiteralPattern.js.diff Accepts comprehensive object patterns.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitDestructuringArrayPattern5.js.diff Accepts omitted array elements.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitDestructuringArrayPattern4.js.diff Accepts array rest patterns.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitDestructuringArrayPattern3.js.diff Accepts namespace array patterns.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitDestructuringArrayPattern2.js.diff Accepts nested array patterns.
testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitDestructuringArrayPattern1.js.diff Accepts basic array patterns.
testdata/baselines/reference/submodule/conformance/stringLiteralTypesAndTuples01.js Updates tuple declaration output.
testdata/baselines/reference/submodule/conformance/dependentDestructuredVariables.js Updates object declaration output.
testdata/baselines/reference/submodule/compiler/isolatedDeclarationErrorsExpressions.errors.txt Removes binding-pattern diagnostics.
testdata/baselines/reference/submodule/compiler/destructuredDeclarationEmit.js Records nested destructuring output.
testdata/baselines/reference/submodule/compiler/declarationEmitRetainsJsdocyComments.js Records comments inside patterns.
testdata/baselines/reference/submodule/compiler/declarationEmitOptionalMappedTypePropertyNoStrictNullChecks3.js Records mapped-type pattern output.
testdata/baselines/reference/submodule/compiler/declarationEmitOptionalMappedTypePropertyNoStrictNullChecks2.js Records mapped-type pattern output.
testdata/baselines/reference/submodule/compiler/declarationEmitOptionalMappedTypePropertyNoStrictNullChecks1.js Records mapped-type pattern output.
testdata/baselines/reference/submodule/compiler/declarationEmitNonExportedBindingPattern.js Records non-exported patterns.
testdata/baselines/reference/submodule/compiler/declarationEmitExpressionInExtends6.js Records namespace destructuring.
testdata/baselines/reference/submodule/compiler/declarationEmitDestructuringPrivacyError.js Records privacy-case pattern.
testdata/baselines/reference/submodule/compiler/declarationEmitDestructuringObjectLiteralPattern2.js Records nested object patterns.
testdata/baselines/reference/submodule/compiler/declarationEmitDestructuringObjectLiteralPattern1.js Records object patterns.
testdata/baselines/reference/submodule/compiler/declarationEmitDestructuringObjectLiteralPattern.js Records comprehensive object patterns.
testdata/baselines/reference/submodule/compiler/declarationEmitDestructuringArrayPattern5.js Records omitted array elements.
testdata/baselines/reference/submodule/compiler/declarationEmitDestructuringArrayPattern4.js Records array rest patterns.
testdata/baselines/reference/submodule/compiler/declarationEmitDestructuringArrayPattern3.js Records namespace array patterns.
testdata/baselines/reference/submodule/compiler/declarationEmitDestructuringArrayPattern2.js Records nested array patterns.
testdata/baselines/reference/submodule/compiler/declarationEmitDestructuringArrayPattern1.js Records basic array patterns.
testdata/baselines/reference/conformance/dependentDestructuredVariablesNoCrash3.js Updates malformed-pattern emit baseline.
testdata/baselines/reference/compiler/subpathImportDeclarationEmit.js Preserves patterns across subpath imports.
testdata/baselines/reference/compiler/declarationEmitVariableBindingPatternsRetained.types Records inferred types.
testdata/baselines/reference/compiler/declarationEmitVariableBindingPatternsRetained.symbols Records symbol bindings.
testdata/baselines/reference/compiler/declarationEmitVariableBindingPatternsRetained.js Records JavaScript and declaration emit.
testdata/baselines/reference/compiler/declarationEmitSubpathImportsReexport.js Updates re-export declaration output.
internal/transformers/declarations/transform.go Retains variable binding patterns.
internal/pseudochecker/lookup.go Handles symbol-less variables.
internal/checker/nodebuilderimpl.go Resolves symbol-less declaration types.
internal/checker/emitresolver.go Avoids nil-symbol literal checks.

Comment thread internal/transformers/declarations/transform.go
Comment on lines +2 to +4
const func = () => "ok"
const b = { a: func }
export const { a } = b
@weswigham weswigham changed the title Retain binding patterns for variable declarations in declaration emit Retain uninitialized binding patterns for variable declarations in declaration emit Jul 28, 2026
-!!! error TS9019: Binding elements can't be exported directly with --isolatedDeclarations.
export const [, , b = 1]: [number, number, number | undefined] = [0, 1, 2];
~
!!! error TS9019: Binding elements can't be exported directly with --isolatedDeclarations. No newline at end of file

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.

Does this need a refreshed message that mentions the initializer? Sort of curious how this differs from export const foo = 1, though

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.

Follow-up on issues/4254: typeof emit does not happen in export const { ... } = default

4 participants