Preserve error elaboration for indexed access type assignments#3220
Preserve error elaboration for indexed access type assignments#3220WhiteMinds wants to merge 1 commit intomicrosoft:mainfrom
Conversation
When assigning to an indexed access type like this["faa"], the checker resolves the constraint and performs a structural comparison that generates specific error messages (e.g., missing properties or type mismatches). However, reportRelationError unconditionally clears errorChain before reporting the generic "could be instantiated with an arbitrary type" message, discarding the useful elaboration. This change preserves errorChain when the target is an IndexedAccess type, so users see both the generic message and the specific details about what went wrong (e.g., "Property 'key' is missing" or "Types of property 'key' are incompatible"). Fixes microsoft/TypeScript#63206
|
Maybe I don't have context here, but, I don't find the new messages more helpful than the existing one... |
Consider this example: class A {
declare foo: this["faa"];
declare faa: {key: number|null}
fuu() {
this.foo = {} // vague error
this.foo = {key: "str"} // vague error
}
}
let foo: {key: number|null};
foo = {} // precise error
foo = {key: "str"} // precise errorBoth assign to the same underlying type |
| if target.flags&TypeFlagsIndexedAccess == 0 { | ||
| r.errorChain = nil | ||
| } | ||
| r.reportError(diagnostics.X_0_could_be_instantiated_with_an_arbitrary_type_which_could_be_unrelated_to_1, targetType, generalizedSourceType) |
There was a problem hiding this comment.
Looking at the error in general, it looks pretty confusing to have this message anywhere other than at the bottom of an elaboration.
Maybe guard all of this in an if r.errorChain != nil
There was a problem hiding this comment.
Do you mean skipping the entire "could be instantiated..." elaboration when errorChain already has specific diagnostics? Something like adding r.errorChain == nil to the outer guard:
if targetFlags&TypeFlagsTypeParameter != 0 && target != r.c.markerSuperTypeForCheck && target != r.c.markerSubTypeForCheck && r.errorChain == nil {So when the constraint comparison has already produced precise errors (e.g., missing property or type mismatch), we skip the generic message entirely instead of prepending it.
Before (current):
Type '{}' is not assignable to type 'this["faa"]'.
'this["faa"]' could be instantiated with an arbitrary type which could be unrelated to '{}'.
After:
Type '{}' is not assignable to type 'this["faa"]'.
Property 'key' is missing in type '{}' but required in type '{ key: number | null; }'.
Type '{ key: string; }' is not assignable to type 'this["faa"]'.
Type '{ key: string; }' is not assignable to type '{ key: number | null; }'.
Types of property 'key' are incompatible.
Type 'string' is not assignable to type 'number'.
Fixes microsoft/TypeScript#63206
Problem
When assigning to an indexed access type (e.g.
this["faa"]),reportRelationErrorunconditionally clearserrorChainbefore reporting the generic "could be instantiated with an arbitrary type" message, discarding the specific elaboration already computed from the constraint comparison (missing properties, type mismatches, etc.).Fix
Preserve
errorChainwhen the target is anIndexedAccesstype, so users see both the generic message and the specific details.Before
After
Two existing baselines updated to reflect the additional elaboration (no errors removed, only more specific detail added).