Skip to content

Don't report TS1293 for destructured require under --module preserve - #4800

Open
AMR5210 wants to merge 2 commits into
microsoft:mainfrom
AMR5210:fix-preserve-destructured-require
Open

Don't report TS1293 for destructured require under --module preserve#4800
AMR5210 wants to merge 2 commits into
microsoft:mainfrom
AMR5210:fix-preserve-destructured-require

Conversation

@AMR5210

@AMR5210 AMR5210 commented Jul 30, 2026

Copy link
Copy Markdown

Fixes microsoft/TypeScript#63696

Analysis

In a .cjs file checked with checkJs, a destructured require is reported as ESM syntax:

// main.cjs
const { readFile } = require("./dep.cjs"); // error TS1293
const dep = require("./dep.cjs");          // no error

checkAliasSymbol runs for every alias declaration, and three members of
AliasDeclarationNode are CommonJS require forms rather than ESM syntax:

  • ImportEqualsDeclaration: import fs = require("node:fs")
  • VariableDeclarationInitializedTo<RequireOrImportCall | AccessExpression>: const fs = require("node:fs")
  • BindingElementOfBareOrAccessedRequire: const { readFile } = require("node:fs")

The --module preserve branch excluded the first two but not the third, so a
destructured require was treated as ESM. This is also why the error is
reported on the binding name rather than on the statement.

The check was introduced upstream in microsoft/TypeScript#58825 (TypeScript 5.6,
matching the reported 5.5 to 5.6 regression) and ported here as-is. It is still
present in 5.9, so per CONTRIBUTING it is fixed here rather than in Strada.

Fix

Exclude binding elements from the check, alongside the two require forms that
were already exempt.

I also considered adding !ast.IsInJSFile(node) to mirror the
verbatimModuleSyntax branch directly above, but rejected it: this is the only
site that reports TS1293, and ESM imports in a .cjs file are reported through
their ImportSpecifier/ImportClause aliases, so exempting JS files wholesale
would stop flagging genuine ESM syntax in CommonJS JavaScript. Within
AliasDeclarationNode, a BindingElement can only ever be a require
destructure, so excluding it is the narrow fix.

The new test covers the destructured form, the plain form as a control, and, in
a separate file, a real ESM import in a .cjs file, which must still error. The
baseline keeps that error, demonstrating the fix does not over-broaden.

Copilot Checklist

I successfully ran these commands at the end of my session, and they completed without error:

  • npx hereby build
  • npx hereby test
  • npx hereby lint
  • npx hereby format

AI assistance disclosure: This change was authored with assistance from
Claude Code. I have reviewed and understand the resulting changes and will
respond to review feedback.

AMR5210 added 2 commits July 31, 2026 03:13
Records current behavior: `const { readFile } = require("./dep.cjs")` in a
.cjs file reports TS1293 even though it is CommonJS, not ESM syntax.
AliasDeclarationNode includes BindingElementOfBareOrAccessedRequire, so
`const { readFile } = require("./dep.cjs")` reached the check for ESM
syntax in CommonJS files. Exclude binding elements alongside the
`import =` and plain `const x = require(...)` forms that were already
exempt.
Copilot AI review requested due to automatic review settings July 30, 2026 22:21

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 false TS1293 diagnostics for destructured CommonJS require calls under --module preserve.

Changes:

  • Exempts BindingElement aliases from the ESM syntax check.
  • Adds regression coverage while retaining diagnostics for genuine ESM imports.

Reviewed changes

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

Show a summary per file
File Description
internal/checker/checker.go Exempts destructured require bindings.
testdata/tests/cases/compiler/modulePreserveRequireDestructuring.ts Adds regression and control cases.
testdata/baselines/reference/compiler/modulePreserveRequireDestructuring.errors.txt Verifies only the ESM import errors.
testdata/baselines/reference/compiler/modulePreserveRequireDestructuring.symbols Records expected symbols.
testdata/baselines/reference/compiler/modulePreserveRequireDestructuring.types Records expected inferred types.

@AMR5210

AMR5210 commented Jul 30, 2026

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

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.

False positive on destructured require is verbatimModuleSyntax and module is preserve

2 participants