Visitar URL original
7.1 regression: TS5115 for import("cloudflare:workers") with @cloudflare/workers-types · Issue #65445 · microsoft/TypeScript · GitHub
Skip to content

7.1 regression: TS5115 for import("cloudflare:workers") with @cloudflare/workers-types #65445

Open

Description

@alon-gb

🔎 Search Terms

TS5115, "appear infinitely circular", MaybeCallableProvider, MethodOrProperty, cloudflare:workers, workers-types, dynamic import

🕗 Version & Regression Information

⏯ Playground Link

No link: the code needs the @cloudflare/workers-types package, which the Playground does not have.

💻 Code

Setup (npm, any empty folder):

npm i -D typescript@7.1.0-beta @cloudflare/workers-types@5.20261110.1

tsconfig.json:

{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "noEmit": true,
    "skipLibCheck": true,
    "types": ["@cloudflare/workers-types"]
  },
  "files": ["index.ts"]
}

index.ts (one line):

import("cloudflare:workers").then((mod) => mod);

Run npx tsc -p .

@cloudflare/workers-types 5.20261104.1 fails the same way. await import("cloudflare:workers") without .then passes. A non-callback use of the module passes.

🙁 Actual behavior

$ npx tsc -v
Version 7.1.0-beta
$ npx tsc -p .
index.ts(1,1): error TS5115: Instantiations of the following types appear infinitely circular: 'MethodOrProperty', 'MaybeCallableProvider'.

7.1.0-dev.20261111.1 prints the same error. In a bigger program the same cause also makes the result of a call on a DurableObjectStub<T> (RPC types from the same package) become any, which then gives TS7006 on callback parameters.

🙂 Expected behavior

No error, as in 7.0.2:

$ npx tsc -v
Version 7.0.2
$ npx tsc -p .
$ echo $?
0

The types in @cloudflare/workers-types are valid and 7.0.2 accepts them.

Additional information about the issue

Tested on Linux with Node 24. Package @cloudflare/workers-types is 5.20261110.1 (latest).

Activity

  1. maschwenk commented on Nov 11, 2026

    @maschwenk
    Contributor

    bisected from source: it starts at microsoft/typescript-go#4687 (ee860ff3d7ed), which reports TS2589, and its parent 351840bc5add is clean. #64372 later turned the TS2589 into TS5115

    microsoft/typescript-go#4687 added anonymousSymbol.SetDeclarations(originalSymbol.Declarations()) in getTypeWithSyntheticDefaultImportType. deleting that line on main at 1b54f27457a7 makes the workers-types repro check clean, along with this reduction that needs no package (target: es2022, module: esnext, moduleResolution: bundler):

    declare module "x" {
      type Stubable = (...args: any[]) => any;
      type Result<R> = R extends Stubable ? Provider<R> : Promise<R>;
      type MethodOrProperty<V> = V extends (...args: infer P) => infer R ? (...args: P) => Result<R> : Result<V>;
      type Provider<T> = T extends Stubable ? MethodOrProperty<T> : unknown;
      export function stub<T extends Stubable>(value: T): Provider<T>;
    }
    
    const a = import("x").then((m) => 1);

    with declarations, the synthetic default type of import("x") passes the anonymous type check in couldContainTypeVariables, so inference from the .then callback walks into its members and getErasedSignature erases stub's type parameter to any. Provider<any> is infinite (declare const x: Provider<any> reports TS2589 back to 5.9.3), and p.then((m) => 1) on a Promise<{ stub<T extends Stubable>(value: T): Provider<T> }> already reports TS2589 on 5.9.3, 6.0.3 and 7.0.2. what's new is that the import() type takes that path

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions