From e71afc32ad8cb4d1e48444fb38a0a2da4d39f989 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 24 Apr 2018 10:02:34 -0700 Subject: [PATCH 1/3] Reinstate type simplification for 'keyof T[K]' as target in relation --- src/compiler/checker.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 75f8715fca7..4e1d71c3d7a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10482,11 +10482,14 @@ namespace ts { } } // A type S is assignable to keyof T if S is assignable to keyof C, where C is the - // constraint of T. - const constraint = getConstraintForRelation((target).type); - if (constraint) { - if (result = isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), reportErrors)) { - return result; + // simplified form of T or, if T doesn't simplify, the constraint of T. + if (relation !== definitelyAssignableRelation) { + const simplified = getSimplifiedType((target).type); + const constraint = simplified !== (target).type ? simplified : getConstraintOfType((target).type); + if (constraint) { + if (result = isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), reportErrors)) { + return result; + } } } } From 57ef618120f9f7463bf9cf0edcbf8be793287e59 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 24 Apr 2018 10:02:47 -0700 Subject: [PATCH 2/3] Add regression test --- .../conformance/types/keyof/keyofAndIndexedAccess.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts index e0c1f544d97..6388245316d 100644 --- a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts @@ -567,3 +567,12 @@ function f3>(t: T, k: K, tk: T[K]): void { type Predicates = { [T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T] } + +// Repros from #23592 + +type Example = { [K in keyof T]: T[K]["prop"] }; +type Result = Example<{ a: { prop: string }; b: { prop: number } }>; + +type Helper2 = { [K in keyof T]: Extract }; +type Example2 = { [K in keyof Helper2]: Helper2[K]["prop"] }; +type Result2 = Example2<{ 1: { prop: string }; 2: { prop: number } }>; From 08c288d4f99e8903d4e92cb96c3776c7d8bddc42 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 24 Apr 2018 10:02:54 -0700 Subject: [PATCH 3/3] Accept new baselines --- .../reference/keyofAndIndexedAccess.js | 40 +++++++++++++++ .../reference/keyofAndIndexedAccess.symbols | 49 +++++++++++++++++++ .../reference/keyofAndIndexedAccess.types | 49 +++++++++++++++++++ 3 files changed, 138 insertions(+) diff --git a/tests/baselines/reference/keyofAndIndexedAccess.js b/tests/baselines/reference/keyofAndIndexedAccess.js index 422cef5a574..bd8404f9ae0 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.js +++ b/tests/baselines/reference/keyofAndIndexedAccess.js @@ -565,6 +565,15 @@ function f3>(t: T, k: K, tk: T[K]): void { type Predicates = { [T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T] } + +// Repros from #23592 + +type Example = { [K in keyof T]: T[K]["prop"] }; +type Result = Example<{ a: { prop: string }; b: { prop: number } }>; + +type Helper2 = { [K in keyof T]: Extract }; +type Example2 = { [K in keyof Helper2]: Helper2[K]["prop"] }; +type Result2 = Example2<{ 1: { prop: string }; 2: { prop: number } }>; //// [keyofAndIndexedAccess.js] @@ -1212,3 +1221,34 @@ declare function f3>(t: T, k: K, tk: T[K]) declare type Predicates = { [T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]; }; +declare type Example = { + [K in keyof T]: T[K]["prop"]; +}; +declare type Result = Example<{ + a: { + prop: string; + }; + b: { + prop: number; + }; +}>; +declare type Helper2 = { + [K in keyof T]: Extract; +}; +declare type Example2 = { + [K in keyof Helper2]: Helper2[K]["prop"]; +}; +declare type Result2 = Example2<{ + 1: { + prop: string; + }; + 2: { + prop: number; + }; +}>; diff --git a/tests/baselines/reference/keyofAndIndexedAccess.symbols b/tests/baselines/reference/keyofAndIndexedAccess.symbols index b1206a49388..118a6fb3bd6 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccess.symbols @@ -2010,3 +2010,52 @@ type Predicates = { >T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 564, 3)) } +// Repros from #23592 + +type Example = { [K in keyof T]: T[K]["prop"] }; +>Example : Symbol(Example, Decl(keyofAndIndexedAccess.ts, 565, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 569, 13)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 569, 26)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 569, 13)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 569, 42)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 569, 63)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 569, 13)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 569, 13)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 569, 63)) + +type Result = Example<{ a: { prop: string }; b: { prop: number } }>; +>Result : Symbol(Result, Decl(keyofAndIndexedAccess.ts, 569, 93)) +>Example : Symbol(Example, Decl(keyofAndIndexedAccess.ts, 565, 1)) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 570, 23)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 570, 28)) +>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 570, 44)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 570, 49)) + +type Helper2 = { [K in keyof T]: Extract }; +>Helper2 : Symbol(Helper2, Decl(keyofAndIndexedAccess.ts, 570, 68)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 572, 13)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 572, 21)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 572, 13)) +>Extract : Symbol(Extract, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 572, 13)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 572, 21)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 572, 51)) + +type Example2 = { [K in keyof Helper2]: Helper2[K]["prop"] }; +>Example2 : Symbol(Example2, Decl(keyofAndIndexedAccess.ts, 572, 67)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 573, 14)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 573, 22)) +>Helper2 : Symbol(Helper2, Decl(keyofAndIndexedAccess.ts, 570, 68)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 573, 14)) +>Helper2 : Symbol(Helper2, Decl(keyofAndIndexedAccess.ts, 570, 68)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 573, 14)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 573, 22)) + +type Result2 = Example2<{ 1: { prop: string }; 2: { prop: number } }>; +>Result2 : Symbol(Result2, Decl(keyofAndIndexedAccess.ts, 573, 70)) +>Example2 : Symbol(Example2, Decl(keyofAndIndexedAccess.ts, 572, 67)) +>1 : Symbol(1, Decl(keyofAndIndexedAccess.ts, 574, 25)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 574, 30)) +>2 : Symbol(2, Decl(keyofAndIndexedAccess.ts, 574, 46)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 574, 51)) + diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types index 4e41b58e664..3e857c6dcd5 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.types +++ b/tests/baselines/reference/keyofAndIndexedAccess.types @@ -2345,3 +2345,52 @@ type Predicates = { >T : T } +// Repros from #23592 + +type Example = { [K in keyof T]: T[K]["prop"] }; +>Example : Example +>T : T +>K : K +>T : T +>prop : any +>K : K +>T : T +>T : T +>K : K + +type Result = Example<{ a: { prop: string }; b: { prop: number } }>; +>Result : Example<{ a: { prop: string; }; b: { prop: number; }; }> +>Example : Example +>a : { prop: string; } +>prop : string +>b : { prop: number; } +>prop : number + +type Helper2 = { [K in keyof T]: Extract }; +>Helper2 : Helper2 +>T : T +>K : K +>T : T +>Extract : Extract +>T : T +>K : K +>prop : any + +type Example2 = { [K in keyof Helper2]: Helper2[K]["prop"] }; +>Example2 : Example2 +>T : T +>K : K +>Helper2 : Helper2 +>T : T +>Helper2 : Helper2 +>T : T +>K : K + +type Result2 = Example2<{ 1: { prop: string }; 2: { prop: number } }>; +>Result2 : Example2<{ 1: { prop: string; }; 2: { prop: number; }; }> +>Example2 : Example2 +>1 : { prop: string; } +>prop : string +>2 : { prop: number; } +>prop : number +