Skip to content

Template inference preserves fresh object-literal identity, causing false(?) type mismatch #4312

Description

@mnsaglam

Bug Description

When a bare template parameter T is inferred from an object literal, Closure Compiler appears to bind T to the exact anonymous object-literal type of that expression, instead of widening it to a structural record type.

As a result, a later argument with the same structural shape is rejected, even though:

  • the same shape is assignable through typedef {{...}}
  • the same shape is assignable through inline record annotations like {{a: string}}

Small repro

// a.js
/** @template T */
class Box {
  /** @param {!T} value */
  constructor(value) {}

  /** @param {!T} other */
  same(other) {}
}
new Box({a: "a"}).same({a: "a"});
java -jar bazel-bin/compiler_uberjar_deploy.jar \
  --compilation_level=ADVANCED \
  --language_in=ECMASCRIPT_NEXT \
  --language_out=ECMASCRIPT_NEXT \
  --jscomp_error=checkTypes a.js
a.js:10:23: ERROR - [JSC_TYPE_MISMATCH] actual parameter 1 of Box.prototype.same does not match formal parameter
found   : {a: string}
required: {a: string}
  10| new Box({a: "a"}).same({a: "a"});

Metadata

Metadata

Assignees

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