Summary
An inferred (un-annotated) method return type on a class expression (const C = class { … }) is not propagated to call sites, so new C().method() is typed too loosely. The same code on a class declaration type-checks fine — class declarations got inferred-method-return propagation via #661/#658, but class expressions were not included.
Repro
// Class DECLARATION — OK
class Range {
constructor(public start: number, public end: number) {}
*gen() { for (let i = this.start; i < this.end; i++) yield i; } // inferred Generator<number>
}
let sum = 0;
for (const n of new Range(1, 5).gen()) sum += n; // n: number → OK, prints 10
console.log(sum);
// Class EXPRESSION — fails type-check
const Range = class {
constructor(public start: number, public end: number) {}
*gen() { for (let i = this.start; i < this.end; i++) yield i; }
};
let sum = 0;
for (const n of new Range(1, 5).gen()) sum += n; // Type Error: Compound assignment requires numeric operands
console.log(sum);
The failure is in the type checker (VisitCompoundAssign), in both back ends — new Range(...).gen()'s element type comes back non-numeric because the method's inferred Generator<number> return isn't visible at the call site. Annotating the method (*gen(): Generator<number>) works around it.
Scope
Type-checker only (codegen is unaffected — compiled class-expression generator methods run correctly once annotated, per #765). Likely generalizes to any inferred method return on a class expression, not just generators. Discovered while adding #765 tests.
Summary
An inferred (un-annotated) method return type on a class expression (
const C = class { … }) is not propagated to call sites, sonew C().method()is typed too loosely. The same code on a class declaration type-checks fine — class declarations got inferred-method-return propagation via #661/#658, but class expressions were not included.Repro
The failure is in the type checker (
VisitCompoundAssign), in both back ends —new Range(...).gen()'s element type comes back non-numeric because the method's inferredGenerator<number>return isn't visible at the call site. Annotating the method (*gen(): Generator<number>) works around it.Scope
Type-checker only (codegen is unaffected — compiled class-expression generator methods run correctly once annotated, per #765). Likely generalizes to any inferred method return on a class expression, not just generators. Discovered while adding #765 tests.