diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7a1364c7a1f7b..bc3bd0ebd8a99 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12254,7 +12254,8 @@ namespace ts { else if (target.flags & TypeFlags.IndexedAccess) { // A type S is related to a type T[K], where T and K aren't both type variables, if S is related to C, // where C is the base constraint of T[K] - if (relation !== identityRelation && !(isGenericObjectType((target).objectType) && isGenericIndexType((target).indexType))) { + if (relation !== identityRelation && relation !== definitelyAssignableRelation && + !(isGenericObjectType((target).objectType) && isGenericIndexType((target).indexType))) { const constraint = getBaseConstraintOfType(target); if (constraint && constraint !== target) { if (result = isRelatedTo(source, constraint, reportErrors)) { diff --git a/tests/baselines/reference/conditionalTypes2.errors.txt b/tests/baselines/reference/conditionalTypes2.errors.txt index fdf210f47932a..322cbe1e7bb47 100644 --- a/tests/baselines/reference/conditionalTypes2.errors.txt +++ b/tests/baselines/reference/conditionalTypes2.errors.txt @@ -203,4 +203,13 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2 type C2 = T extends object ? { [Q in keyof T]: C2; } : T; + + // Repro from #28654 + + type MaybeTrue = true extends T["b"] ? "yes" : "no"; + + type T0 = MaybeTrue<{ b: never }> // "no" + type T1 = MaybeTrue<{ b: false }>; // "no" + type T2 = MaybeTrue<{ b: true }>; // "yes" + type T3 = MaybeTrue<{ b: boolean }>; // "yes" \ No newline at end of file diff --git a/tests/baselines/reference/conditionalTypes2.js b/tests/baselines/reference/conditionalTypes2.js index 1f95e7eb8d9f2..02581ab0015b6 100644 --- a/tests/baselines/reference/conditionalTypes2.js +++ b/tests/baselines/reference/conditionalTypes2.js @@ -145,6 +145,15 @@ type B2 = type C2 = T extends object ? { [Q in keyof T]: C2; } : T; + +// Repro from #28654 + +type MaybeTrue = true extends T["b"] ? "yes" : "no"; + +type T0 = MaybeTrue<{ b: never }> // "no" +type T1 = MaybeTrue<{ b: false }>; // "no" +type T2 = MaybeTrue<{ b: true }>; // "yes" +type T3 = MaybeTrue<{ b: boolean }>; // "yes" //// [conditionalTypes2.js] @@ -304,3 +313,18 @@ declare type B2 = T extends object ? T extends any[] ? T : { declare type C2 = T extends object ? { [Q in keyof T]: C2; } : T; +declare type MaybeTrue = true extends T["b"] ? "yes" : "no"; +declare type T0 = MaybeTrue<{ + b: never; +}>; +declare type T1 = MaybeTrue<{ + b: false; +}>; +declare type T2 = MaybeTrue<{ + b: true; +}>; +declare type T3 = MaybeTrue<{ + b: boolean; +}>; diff --git a/tests/baselines/reference/conditionalTypes2.symbols b/tests/baselines/reference/conditionalTypes2.symbols index c52179e81b01c..b9098616f0fda 100644 --- a/tests/baselines/reference/conditionalTypes2.symbols +++ b/tests/baselines/reference/conditionalTypes2.symbols @@ -551,3 +551,31 @@ type C2 = >E : Symbol(E, Decl(conditionalTypes2.ts, 144, 13)) >T : Symbol(T, Decl(conditionalTypes2.ts, 144, 8)) +// Repro from #28654 + +type MaybeTrue = true extends T["b"] ? "yes" : "no"; +>MaybeTrue : Symbol(MaybeTrue, Decl(conditionalTypes2.ts, 145, 63)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 149, 15)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 149, 26)) +>T : Symbol(T, Decl(conditionalTypes2.ts, 149, 15)) + +type T0 = MaybeTrue<{ b: never }> // "no" +>T0 : Symbol(T0, Decl(conditionalTypes2.ts, 149, 78)) +>MaybeTrue : Symbol(MaybeTrue, Decl(conditionalTypes2.ts, 145, 63)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 151, 21)) + +type T1 = MaybeTrue<{ b: false }>; // "no" +>T1 : Symbol(T1, Decl(conditionalTypes2.ts, 151, 33)) +>MaybeTrue : Symbol(MaybeTrue, Decl(conditionalTypes2.ts, 145, 63)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 152, 21)) + +type T2 = MaybeTrue<{ b: true }>; // "yes" +>T2 : Symbol(T2, Decl(conditionalTypes2.ts, 152, 34)) +>MaybeTrue : Symbol(MaybeTrue, Decl(conditionalTypes2.ts, 145, 63)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 153, 21)) + +type T3 = MaybeTrue<{ b: boolean }>; // "yes" +>T3 : Symbol(T3, Decl(conditionalTypes2.ts, 153, 33)) +>MaybeTrue : Symbol(MaybeTrue, Decl(conditionalTypes2.ts, 145, 63)) +>b : Symbol(b, Decl(conditionalTypes2.ts, 154, 21)) + diff --git a/tests/baselines/reference/conditionalTypes2.types b/tests/baselines/reference/conditionalTypes2.types index 58ce7e5d5b49e..e500d21d36b5b 100644 --- a/tests/baselines/reference/conditionalTypes2.types +++ b/tests/baselines/reference/conditionalTypes2.types @@ -341,3 +341,28 @@ type C2 = T extends object ? { [Q in keyof T]: C2; } : T; +// Repro from #28654 + +type MaybeTrue = true extends T["b"] ? "yes" : "no"; +>MaybeTrue : MaybeTrue +>b : boolean +>true : true + +type T0 = MaybeTrue<{ b: never }> // "no" +>T0 : "no" +>b : never + +type T1 = MaybeTrue<{ b: false }>; // "no" +>T1 : "no" +>b : false +>false : false + +type T2 = MaybeTrue<{ b: true }>; // "yes" +>T2 : "yes" +>b : true +>true : true + +type T3 = MaybeTrue<{ b: boolean }>; // "yes" +>T3 : "yes" +>b : boolean + diff --git a/tests/cases/conformance/types/conditional/conditionalTypes2.ts b/tests/cases/conformance/types/conditional/conditionalTypes2.ts index be75894546944..2fd13ceff85cf 100644 --- a/tests/cases/conformance/types/conditional/conditionalTypes2.ts +++ b/tests/cases/conformance/types/conditional/conditionalTypes2.ts @@ -147,3 +147,12 @@ type B2 = type C2 = T extends object ? { [Q in keyof T]: C2; } : T; + +// Repro from #28654 + +type MaybeTrue = true extends T["b"] ? "yes" : "no"; + +type T0 = MaybeTrue<{ b: never }> // "no" +type T1 = MaybeTrue<{ b: false }>; // "no" +type T2 = MaybeTrue<{ b: true }>; // "yes" +type T3 = MaybeTrue<{ b: boolean }>; // "yes"