Skip to content

With the language service plugin enabled, delete of an index-signature property reports TS2790 #820

Closed

Description

@candrewlee14

With the @effect/language-service plugin enabled, effect-tsgo reports TS2790 for delete of an index-signature property (see the table below for exactly which). TypeScript allows it (5.9.3 and 7.0.2), and effect-tsgo itself allows it with the plugin off.

Versions: @effect/tsgo 0.51.1 (Version 7.0.2+effect-tsgo.0.51.1), typescript 7.0.2, macOS arm64.

Repro

index.ts:

declare const map: { [key: string]: number };
delete map.x;

export {};

tsconfig.json:

{
  "compilerOptions": {
    "strict": true,
    "noEmit": true,
    "target": "ES2023",
    "lib": ["ES2023"],
    "types": [],
    "plugins": [{ "name": "@effect/language-service" }]
  },
  "files": ["index.ts"]
}
$ "$(node -e 'import("@effect/tsgo/lib/getExePath").then(m=>console.log(m.default()))')" -p tsconfig.json
index.ts(2,8): error TS2790: The operand of a 'delete' operator must be optional.
Compiler Plugin Result
effect-tsgo 0.51.1 on TS2790
effect-tsgo 0.51.1 off no error
typescript 7.0.2 tsc on (ignored) no error

Expected: no error; the plugin should not change this core diagnostic.

What triggers it: delete of a property that comes only from an index signature (no declared optional property):

Operand's declaration exactOptionalPropertyTypes off on
{ [key: string]: number } TS2790 TS2790
{ [key: string]: string | undefined } (e.g. @types/node's process.env) no error TS2790
Record<string, unknown> no error no error
{ a?: number } no error no error

In a real codebase that refuses Object.fromEntries(...) results and, with exactOptionalPropertyTypes, delete process.env.PATH. Upstream tsc 7.0.2 accepts all of these.

Across 53 TypeScript projects in our monorepo, this was the only difference in compiler diagnostics between effect-tsgo with the plugin and upstream TypeScript 7.0.2. Until it's fixed we compile with upstream and run effect-tsgo diagnostics as a second pass.

Activity

  1. mattiamanzati commented on Oct 11, 2026

    @mattiamanzati
    Contributor

    Confirmed on Linux x64 with a locally built executable from commit 181b2b3fa1a9d1811a26a36935638ada2bbdf35c.

    Version 7.1.0-dev+effect-tsgo.0.51.1
    

    The minimal index-signature example has these results:

    • With the Effect plugin enabled, TS2790 and exit code 2.
    • With the plugin removed, no diagnostics and exit code 0.
    • With the plugin enabled but both experimentalApiUsage and unstableApiUsage set to "off", no diagnostics and exit code 0.

    The configuration for the third run is:

    {
      "compilerOptions": {
        "strict": true,
        "noEmit": true,
        "target": "ES2023",
        "types": [],
        "plugins": [{
          "name": "@effect/language-service",
          "diagnosticSeverity": {
            "experimentalApiUsage": "off",
            "unstableApiUsage": "off"
          }
        }]
      },
      "files": ["index.ts"]
    }

    Source inspection points to a checker-state interaction. The stability usage rules call GetSymbolAtLocation, which can cache the synthetic index-signature symbol. A later type query can recheck the delete expression against that cached symbol and report the optionality error. The relevant code is in internal/rules/stability_api_usage.go and checkDeleteExpression in the compiler checker.

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