microsoft / microsoft/TypeScript

TS5097 is not reported for `require()` in checked JS or for clause-less side-effect imports

オープン
#64,028 コメント 0 件 リアクション 1 件 担当者 3 名 GitHub で見る

@RyanCavanaugh がすでに取り組んでいます。

2026年8月26日 から。

Bug
主要言語
Go
スター
111k
フォーク
14.3k
平均マージ
2日 4時間
マージ済み PR(30日)
132

説明

Regression from `typescript@6.0.2` to `typescript@7.0.2`. Also reproduces on `@typescript/native-preview@7.0.0-dev.20260707.2` and on current `main`. node v24.13.0, darwin/arm64.

## Steps to reproduce

Three files, no `tsconfig.json`:

`lib.ts`

```ts
export const value = 1;
```

`require.js`

```js
// @ts-check
const { value } = require('./lib.ts');
console.log(value);
```

`side-effect.ts`

```ts
import './lib.ts';
```

```sh
tsc --noEmit --allowJs require.js side-effect.ts
```

## Behavior with `typescript@6.0.2`

```
require.js(2,27): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
side-effect.ts(1,8): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
```

## Behavior with `typescript@7.0.2`

No output — both are silently accepted.

This is not a module-resolution difference: 7.0 resolves `require('./lib.ts')` and type-checks against it. Changing `console.log(value)` to `value(123)` yields the same TS2349 from both versions at the same position — only TS5097 is missing.

## Root cause

The two versions guard the diagnostic differently:

```
7.0 — tsc/internal/checker/checker.go:15334 if ast.FindAncestor(location, ast.IsEmittableImport) != nil {
6.0 — src/compiler/checker.ts:4779 if (errorNode && !(importOrExport?.isTypeOnly || findAncestor(location, isImportTypeNode))) {
```

7.0 asks *"will this import survive emit?"*; 6.0 asks *"is this explicitly type-only?"*. The answers differ for exactly two shapes: a CommonJS `require()`, which is a plain `CallExpression` that [`IsEmittableImport`](https://github.com/microsoft/TypeScript/blob/main/tsc/internal/ast/utilities.go#L3205) never matched, and a clause-less side-effect import, which stopped matching in [typescript-go#1198](https://github.com/microsoft/typescript-go/pull/1198) — a fix for [typescript-go#1190](https://github.com/microsoft/typescript-go/issues/1190) in the adjacent `.d.ts` branch, which shares the same predicate.

## Full matrix

| case | 6.0.2 | 7.0.2 |
| --- | --- | --- |
| `require('./lib.ts')` in checked JS | TS5097 | — |
| `import './lib.ts'` | TS5097 | — |
| `import { value } from './lib.ts'` | TS5097 | TS5097 |
| `import { value } from './lib.ts'` in JS | TS5097 | TS5097 |
| `export { value } from './lib.ts'` | TS5097 | TS5097 |
| `import('./lib.ts')` | TS5097 | TS5097 |
| `import lib = require('./lib.ts')` | TS5097 | TS5097 |
| `import type { Thing } from './lib.ts'` | — | — |
| `export type { Thing } from './lib.ts'` | — | — |
| `import('./lib.ts').Thing` in type position | — | — |
| `import './types.d.ts'` | — | — |

The versions disagree only on the first two rows; the last four are negative cases where both correctly stay silent.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。