From 6031cbbfda1708bdfdf1008059bef4fb9fab627f Mon Sep 17 00:00:00 2001 From: whitemind Date: Sat, 21 Mar 2026 12:00:38 +0800 Subject: [PATCH] Preserve error elaboration for indexed access type assignments 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 errorInfo before reporting the generic "could be instantiated with an arbitrary type" message, discarding the useful elaboration. This change preserves errorInfo 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 #63206 --- src/compiler/checker.ts | 9 ++++++++- .../reference/mappedTypeRelationships.errors.txt | 16 ++++++++++++++++ ...imitiveConstraintOfIndexAccessType.errors.txt | 2 ++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0567712f11da3..e6bceecfcd4ab 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22656,7 +22656,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ); } else { - errorInfo = undefined; + // When the target is an indexed access type (e.g. this["faa"]), preserve any + // specific error elaboration from the constraint comparison (e.g., missing + // property or type mismatch errors) rather than discarding them. For plain + // type parameters, clear the error info as the constraint-based errors may + // be misleading. + if (!(target.flags & TypeFlags.IndexedAccess)) { + errorInfo = undefined; + } reportError( Diagnostics._0_could_be_instantiated_with_an_arbitrary_type_which_could_be_unrelated_to_1, targetType, diff --git a/tests/baselines/reference/mappedTypeRelationships.errors.txt b/tests/baselines/reference/mappedTypeRelationships.errors.txt index 1918a9532f32d..94aec8bf42357 100644 --- a/tests/baselines/reference/mappedTypeRelationships.errors.txt +++ b/tests/baselines/reference/mappedTypeRelationships.errors.txt @@ -10,15 +10,23 @@ mappedTypeRelationships.ts(25,5): error TS2536: Type 'K' cannot be used to index mappedTypeRelationships.ts(26,12): error TS2536: Type 'K' cannot be used to index type 'T'. mappedTypeRelationships.ts(30,5): error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'T[keyof T]'. 'T[keyof T]' could be instantiated with an arbitrary type which could be unrelated to 'T[keyof T] | undefined'. + Type 'undefined' is not assignable to type 'T[keyof T]'. + 'T[keyof T]' could be instantiated with an arbitrary type which could be unrelated to 'undefined'. mappedTypeRelationships.ts(35,5): error TS2322: Type 'T[K] | undefined' is not assignable to type 'T[K]'. 'T[K]' could be instantiated with an arbitrary type which could be unrelated to 'T[K] | undefined'. + Type 'undefined' is not assignable to type 'T[K]'. + 'T[K]' could be instantiated with an arbitrary type which could be unrelated to 'undefined'. mappedTypeRelationships.ts(40,5): error TS2322: Type 'U[keyof T] | undefined' is not assignable to type 'T[keyof T]'. 'T[keyof T]' could be instantiated with an arbitrary type which could be unrelated to 'U[keyof T] | undefined'. + Type 'undefined' is not assignable to type 'T[keyof T]'. + 'T[keyof T]' could be instantiated with an arbitrary type which could be unrelated to 'undefined'. mappedTypeRelationships.ts(41,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T] | undefined'. Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'U[keyof T] | undefined'. Type 'T[string]' is not assignable to type 'U[keyof T] | undefined'. mappedTypeRelationships.ts(45,5): error TS2322: Type 'U[K] | undefined' is not assignable to type 'T[K]'. 'T[K]' could be instantiated with an arbitrary type which could be unrelated to 'U[K] | undefined'. + Type 'undefined' is not assignable to type 'T[K]'. + 'T[K]' could be instantiated with an arbitrary type which could be unrelated to 'undefined'. mappedTypeRelationships.ts(46,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K] | undefined'. Type 'T[keyof T]' is not assignable to type 'U[K] | undefined'. Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'U[K] | undefined'. @@ -125,6 +133,8 @@ mappedTypeRelationships.ts(168,5): error TS2322: Type '{ [P in K]: T[P]; }' is n ~~~~ !!! error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'T[keyof T]'. !!! error TS2322: 'T[keyof T]' could be instantiated with an arbitrary type which could be unrelated to 'T[keyof T] | undefined'. +!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'. +!!! error TS2322: 'T[keyof T]' could be instantiated with an arbitrary type which could be unrelated to 'undefined'. y[k] = x[k]; } @@ -133,6 +143,8 @@ mappedTypeRelationships.ts(168,5): error TS2322: Type '{ [P in K]: T[P]; }' is n ~~~~ !!! error TS2322: Type 'T[K] | undefined' is not assignable to type 'T[K]'. !!! error TS2322: 'T[K]' could be instantiated with an arbitrary type which could be unrelated to 'T[K] | undefined'. +!!! error TS2322: Type 'undefined' is not assignable to type 'T[K]'. +!!! error TS2322: 'T[K]' could be instantiated with an arbitrary type which could be unrelated to 'undefined'. y[k] = x[k]; } @@ -141,6 +153,8 @@ mappedTypeRelationships.ts(168,5): error TS2322: Type '{ [P in K]: T[P]; }' is n ~~~~ !!! error TS2322: Type 'U[keyof T] | undefined' is not assignable to type 'T[keyof T]'. !!! error TS2322: 'T[keyof T]' could be instantiated with an arbitrary type which could be unrelated to 'U[keyof T] | undefined'. +!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'. +!!! error TS2322: 'T[keyof T]' could be instantiated with an arbitrary type which could be unrelated to 'undefined'. y[k] = x[k]; // Error ~~~~ !!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T] | undefined'. @@ -153,6 +167,8 @@ mappedTypeRelationships.ts(168,5): error TS2322: Type '{ [P in K]: T[P]; }' is n ~~~~ !!! error TS2322: Type 'U[K] | undefined' is not assignable to type 'T[K]'. !!! error TS2322: 'T[K]' could be instantiated with an arbitrary type which could be unrelated to 'U[K] | undefined'. +!!! error TS2322: Type 'undefined' is not assignable to type 'T[K]'. +!!! error TS2322: 'T[K]' could be instantiated with an arbitrary type which could be unrelated to 'undefined'. y[k] = x[k]; // Error ~~~~ !!! error TS2322: Type 'T[K]' is not assignable to type 'U[K] | undefined'. diff --git a/tests/baselines/reference/nonPrimitiveConstraintOfIndexAccessType.errors.txt b/tests/baselines/reference/nonPrimitiveConstraintOfIndexAccessType.errors.txt index c8b98bc4f1b05..ce7cec19b6ea3 100644 --- a/tests/baselines/reference/nonPrimitiveConstraintOfIndexAccessType.errors.txt +++ b/tests/baselines/reference/nonPrimitiveConstraintOfIndexAccessType.errors.txt @@ -8,6 +8,7 @@ nonPrimitiveConstraintOfIndexAccessType.ts(12,5): error TS2322: Type 'string' is 'T[P]' could be instantiated with an arbitrary type which could be unrelated to 'string'. nonPrimitiveConstraintOfIndexAccessType.ts(15,5): error TS2322: Type 'string' is not assignable to type 'T[P]'. 'T[P]' could be instantiated with an arbitrary type which could be unrelated to 'string'. + Type 'string' is not assignable to type 'never'. nonPrimitiveConstraintOfIndexAccessType.ts(18,5): error TS2322: Type 'string' is not assignable to type 'T[P]'. 'T[P]' could be instantiated with an arbitrary type which could be unrelated to 'string'. nonPrimitiveConstraintOfIndexAccessType.ts(21,5): error TS2322: Type 'string' is not assignable to type 'T[P]'. @@ -51,6 +52,7 @@ nonPrimitiveConstraintOfIndexAccessType.ts(30,5): error TS2322: Type 'string' is ~~ !!! error TS2322: Type 'string' is not assignable to type 'T[P]'. !!! error TS2322: 'T[P]' could be instantiated with an arbitrary type which could be unrelated to 'string'. +!!! error TS2322: Type 'string' is not assignable to type 'never'. } function k(s: string, tp: T[P]): void { tp = s;