typescript-go icon indicating copy to clipboard operation
typescript-go copied to clipboard

Inference from variable reference produces different type argument

Open dragomirtitian opened this issue 2 weeks ago • 1 comments

Steps to reproduce

declare const deepEqual: <T>(actualValue: T, expectedValue: T, message?: string) => void;

const actualValue = { a: "hello", b: undefined, c: "world", d: undefined };
// Fails in ts-go
deepEqual(actualValue, {
    a: "hello",
    c: "world",
});

// Works in both
deepEqual({ a: "hello", b: undefined, c: "world", d: undefined }, {
    a: "hello",
    c: "world",
});

Playground Link

Behavior with [email protected]

Both calls type check

Behavior with tsgo

First call fails to type check with:

src/index.ts:5:24 - error TS2739: Type '{ a: string; c: string; }' is missing the following properties from type '{ a: string; b: undefined; c: string; d: undefined; }': b, d

5 deepEqual(actualValue, {
                         ~
6     a: "hello",
  ~~~~~~~~~~~~~~~
7     c: "world",
  ~~~~~~~~~~~~~~~
8 });

dragomirtitian avatar Dec 10 '25 17:12 dragomirtitian

Bisects to https://github.com/microsoft/typescript-go/pull/1759 that was ported to TS 6.0 ( https://github.com/microsoft/TypeScript/pull/62502 ) so actually we can see the same error in the nightly playground

I think this is actually an improvement. When literal and non-literal canidates are mixed then, in a way, unionObjectAndArrayLiteralCandidates prioritizes non-literals (it puts them at the beginning of the returned candidates). Then based on that prioritization getCommonSupertype+getSingleCommonSupertype now always chose the actualValue's type given the adjusted rules.

Andarist avatar Dec 11 '25 13:12 Andarist

This is working as intended, so I'm closing.

ahejlsberg avatar Dec 18 '25 23:12 ahejlsberg