Skip to content

tsgo fails to report TS2769 for mutually-exclusive object overloads #2583

@r253hmdryou

Description

@r253hmdryou

🔎 Search Terms

  • TS2769
  • exclusive
  • overload
  • tsgo
  • mutually exclusive

🕗 Version & Regression Information

This is not a regression.

The behavior has been observed in current versions of tsgo.
tsc has consistently reported an error for this pattern, while tsgo has never reported one.

I tested the repro with the latest available tsgo build and the issue still reproduces.

This does not appear to be a recently introduced change, but rather a missing or incomplete diagnostic in tsgo’s overload resolution logic.

⏯ Playground Link

N/A — this repro requires tsgo; TypeScript Playground runs tsc.

💻 Code

type A = { a: { x: 1 }; b?: never };
type B = { b: { y: 1 }; a?: never };

export function defineFoo<const N extends string>(name: N, config: A): void;
export function defineFoo<const N extends string>(name: N, config: B): void;
export function defineFoo(name: string, config: unknown) {
  void name;
  void config;
}

// Both a and b provided (mutually exclusive).
defineFoo("foo", {
  // @ts-expect-error - a and b are mutually exclusive; provide exactly one.
  a: { x: 1 },
  b: { y: 1 }
});

🙁 Actual behavior

Running:

$ npm run typecheck:go
> tsgo -p tsconfig.json

produces no errors.
That means tsgo is not reporting an overload resolution failure where tsc clearly does.

🙂 Expected behavior

Running:

$ npm run typecheck

> typecheck
> tsc -p tsconfig.json

src/repro.ts:14:1 - error TS2769: No overload matches this call.
  Overload 1 of 2, '(name: "foo", config: A): void', gave the following error.
    Type '{ y: number; }' is not assignable to type 'undefined'.
  Overload 2 of 2, '(name: "foo", config: B): void', gave the following error.
    Type '{ x: number; }' is not assignable to type 'undefined'.

14 defineFoo("foo", {
   ~~~~~~~~~

  src/repro.ts:3:25
    3 type A = { a: { x: 1 }; b?: never };
                              ~
    The expected type comes from property 'b' which is declared here on type 'A'
  src/repro.ts:4:25
    4 type B = { b: { y: 1 }; a?: never };
                              ~
    The expected type comes from property 'a' which is declared here on type 'B'
  src/repro.ts:8:17
    8 export function defineFoo(name: string, config: unknown) {
                      ~~~~~~~~~
    The call would have succeeded against this implementation, but implementation signatures of overloads are not externally visible.

src/repro.ts:15:3 - error TS2578: Unused '@ts-expect-error' directive.

15   // @ts-expect-error - a and b are mutually exclusive; provide exactly one.
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Found 2 errors in the same file, starting at: src/repro.ts:14

Additional information about the issue

This issue is distinct from #1088 (which concerns @ts-expect-error diagnostic placement).
Here, the core issue is that tsgo does not report an overload resolution error at all.

Related

I also filed the same report in the main TypeScript repo for visibility; linking here for reference:

microsoft/TypeScript#63051

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions