Skip to content

Incremental builds miss diagnostics after UMD declaration changes #64967

Open

Description

@Dunqing

🔎 Search Terms

UMD, export as namespace, incremental, stale diagnostics, affectsGlobalScope

🕗 Version & Regression Information

Reproduced with the Go compiler reporting 7.1.0-beta, built from microsoft/TypeScript commit 3e9236361fa97a9e6c685f4833ac457ae2d8c50a.

The first affected version has not been identified. The latest nightly has not been tested.

⏯ Playground Link

This requires consecutive compiler invocations that reuse .tsbuildinfo; a single Playground compilation does not reproduce it.

💻 Code

Create these four files in a new directory. The minimal library keeps the reproduction independent of installed standard-library files.

tsconfig.json:

{
  "compilerOptions": {
    "strict": true,
    "incremental": true,
    "noEmit": true,
    "types": []
  },
  "include": ["*.ts"]
}

lib.d.ts:

interface Array<T> {}
interface Boolean {}
interface CallableFunction {}
interface Function {}
interface IArguments {}
interface NewableFunction {}
interface Number {}
interface Object {}
interface RegExp {}
interface String {}

umd.d.ts:

export as namespace UmdApi;
export interface Item { value: number }

client.ts:

declare const item: UmdApi.Item;
const checked: number = item.value;
  1. Run the Go compiler from this directory, using an unpatched tsgo binary:

    tsgo -p . --noLib --pretty false

    This succeeds and creates tsconfig.tsbuildinfo.

  2. Change only umd.d.ts to:

    export as namespace UmdApi;
    export interface Item { value: string }
  3. Repeat the same command, keeping the build-info file:

    tsgo -p . --noLib --pretty false
  4. Compare with a compilation that disables incremental reuse:

    tsgo -p . --noLib --pretty false --incremental false

🙁 Actual behavior

The second incremental build produces no diagnostics and exits with code 0, even though item.value is now a string and checked requires a number. client.ts has not changed.

Compiling the same files with --incremental false reports the error and exits with code 2:

client.ts(2,7): error TS2322: Type 'string' is not assignable to type 'number'.

A fresh directory containing the same edited inputs, without build-info, produces the same error.

🙂 Expected behavior

The incremental build should report TS2322, matching a fresh compilation of the same inputs.

Additional information about the issue

Proposed fix: #64966

fileAffectsGlobalScope treats this declaration file as an external module without accounting for the global namespace introduced by export as namespace. As a result, changes to the declaration can leave cached diagnostics for unchanged global consumers intact. The proposed fix checks bound GlobalExports before the external-module early return.

The CLI reproduction above has been verified on the unpatched compiler. The PR's new CLI/watch framework tests and baselines remain pending; they have not been run successfully because required test dependencies are unavailable offline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptDomain: tsc: --incrementalThe issue relates to incremental compilation

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions