Part of #80. Follow-up to #121.
Context
#121 made { (x: number): void }, { new (x): T }, and mixed object types parse. But only the pure single call-signature case is modeled — it resolves to a TypeInfo.Function (TypeChecker.TypeParsing.cs:878). Anything richer is dropped:
- mixed
{ (x: number): void; prop: string } — call signature discarded, only prop survives
- overloaded
{ (x: number): string; (x: string): number }
- construct signatures
{ new (x: number): T } — discarded entirely
TypeInfo.Interface already models these (CallSignatures / ConstructorSignatures, TypeInfo.cs:368-369); TypeInfo.Record does not (TypeInfo.cs:669-696). That asymmetry is the gap.
Scope / approach
- Add fields to
TypeInfo.Record (TypeInfo.cs:669): List<CallSignature>? CallSignatures = null, List<ConstructorSignature>? ConstructorSignatures = null, plus HasCallSignature / IsCallable helpers mirroring Interface (TypeInfo.cs:374-377). Optional defaulted params → none of the 70 new TypeInfo.Record(...) sites break.
- Populate them in
ParseInlineObjectTypeInfo (TypeChecker.TypeParsing.cs:781): the bare-signature members are already detected and skipped (~lines 799-823) — instead, parse the arrow-strings ((params) => ret, new (params) => ret) into TypeInfo.CallSignature / ConstructorSignature (TypeInfo.cs:320, :342) and attach to the Record. Keep the pure-single-call-sig → Function shortcut.
- Reuse existing compat helpers — no new assignability logic:
FunctionMatchesCallSignatures (Compatibility.Callable.cs:12) — wire Record.CallSignatures into the same path the interface uses at Compatibility.cs:704.
ClassMatchesConstructorSignatures (Compatibility.Callable.cs:54) for construct signatures.
- Record↔Record / Record↔Interface signature compatibility.
- Make callable Records invocable at call sites (
TypeChecker.Calls.cs:610): add a TypeInfo.Record { IsCallable: true } branch alongside the existing Interface / GenericInterface dispatch to CheckCallableInterfaceCall.
Acceptance
{ (x:number): string; p: U } is both callable and structurally type-checked on p.
- Overloaded call signatures resolve at call sites.
assignmentCompatWithCallSignatures* / assignmentCompatWithConstructSignatures* tests currently landing in Fail due to dropped modeling move toward Pass (regen baseline with SHARPTS_TSCONFORMANCE_UPDATE_BASELINE=1; no regressions).
Blast radius
Low. New Record fields are optional/defaulted (70 construction sites unaffected); compat helpers already exist. Main work is ParseInlineObjectTypeInfo population + one call-site branch.
Part of #80. Follow-up to #121.
Context
#121 made
{ (x: number): void },{ new (x): T }, and mixed object types parse. But only the pure single call-signature case is modeled — it resolves to aTypeInfo.Function(TypeChecker.TypeParsing.cs:878). Anything richer is dropped:{ (x: number): void; prop: string }— call signature discarded, onlypropsurvives{ (x: number): string; (x: string): number }{ new (x: number): T }— discarded entirelyTypeInfo.Interfacealready models these (CallSignatures/ConstructorSignatures,TypeInfo.cs:368-369);TypeInfo.Recorddoes not (TypeInfo.cs:669-696). That asymmetry is the gap.Scope / approach
TypeInfo.Record(TypeInfo.cs:669):List<CallSignature>? CallSignatures = null,List<ConstructorSignature>? ConstructorSignatures = null, plusHasCallSignature/IsCallablehelpers mirroringInterface(TypeInfo.cs:374-377). Optional defaulted params → none of the 70new TypeInfo.Record(...)sites break.ParseInlineObjectTypeInfo(TypeChecker.TypeParsing.cs:781): the bare-signature members are already detected and skipped (~lines 799-823) — instead, parse the arrow-strings ((params) => ret,new (params) => ret) intoTypeInfo.CallSignature/ConstructorSignature(TypeInfo.cs:320,:342) and attach to the Record. Keep the pure-single-call-sig →Functionshortcut.FunctionMatchesCallSignatures(Compatibility.Callable.cs:12) — wireRecord.CallSignaturesinto the same path the interface uses atCompatibility.cs:704.ClassMatchesConstructorSignatures(Compatibility.Callable.cs:54) for construct signatures.TypeChecker.Calls.cs:610): add aTypeInfo.Record { IsCallable: true }branch alongside the existingInterface/GenericInterfacedispatch toCheckCallableInterfaceCall.Acceptance
{ (x:number): string; p: U }is both callable and structurally type-checked onp.assignmentCompatWithCallSignatures*/assignmentCompatWithConstructSignatures*tests currently landing inFaildue to dropped modeling move towardPass(regen baseline withSHARPTS_TSCONFORMANCE_UPDATE_BASELINE=1; no regressions).Blast radius
Low. New Record fields are optional/defaulted (70 construction sites unaffected); compat helpers already exist. Main work is
ParseInlineObjectTypeInfopopulation + one call-site branch.