Skip to content

Commit 7f4a132

Browse files
authored
Merge pull request #19564 from Microsoft/fixGenericMappedTypeRelationships
Fix generic mapped type relationships
2 parents 6de69df + c0c1b6f commit 7f4a132

File tree

6 files changed

+179
-20
lines changed

6 files changed

+179
-20
lines changed

src/compiler/checker.ts

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9460,32 +9460,30 @@ namespace ts {
94609460
}
94619461
}
94629462
}
9463+
else if (isGenericMappedType(target) && !isGenericMappedType(source) && getConstraintTypeFromMappedType(<MappedType>target) === getIndexType(source)) {
9464+
// A source type T is related to a target type { [P in keyof T]: X } if T[P] is related to X.
9465+
const indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(<MappedType>target));
9466+
const templateType = getTemplateTypeFromMappedType(<MappedType>target);
9467+
if (result = isRelatedTo(indexedAccessType, templateType, reportErrors)) {
9468+
errorInfo = saveErrorInfo;
9469+
return result;
9470+
}
9471+
}
94639472

94649473
if (source.flags & TypeFlags.TypeParameter) {
9465-
// A source type T is related to a target type { [P in keyof T]: X } if T[P] is related to X.
9466-
if (getObjectFlags(target) & ObjectFlags.Mapped && getConstraintTypeFromMappedType(<MappedType>target) === getIndexType(source)) {
9467-
const indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(<MappedType>target));
9468-
const templateType = getTemplateTypeFromMappedType(<MappedType>target);
9469-
if (result = isRelatedTo(indexedAccessType, templateType, reportErrors)) {
9474+
let constraint = getConstraintOfTypeParameter(<TypeParameter>source);
9475+
// A type parameter with no constraint is not related to the non-primitive object type.
9476+
if (constraint || !(target.flags & TypeFlags.NonPrimitive)) {
9477+
if (!constraint || constraint.flags & TypeFlags.Any) {
9478+
constraint = emptyObjectType;
9479+
}
9480+
// Report constraint errors only if the constraint is not the empty object type
9481+
const reportConstraintErrors = reportErrors && constraint !== emptyObjectType;
9482+
if (result = isRelatedTo(constraint, target, reportConstraintErrors)) {
94709483
errorInfo = saveErrorInfo;
94719484
return result;
94729485
}
94739486
}
9474-
else {
9475-
let constraint = getConstraintOfTypeParameter(<TypeParameter>source);
9476-
// A type parameter with no constraint is not related to the non-primitive object type.
9477-
if (constraint || !(target.flags & TypeFlags.NonPrimitive)) {
9478-
if (!constraint || constraint.flags & TypeFlags.Any) {
9479-
constraint = emptyObjectType;
9480-
}
9481-
// Report constraint errors only if the constraint is not the empty object type
9482-
const reportConstraintErrors = reportErrors && constraint !== emptyObjectType;
9483-
if (result = isRelatedTo(constraint, target, reportConstraintErrors)) {
9484-
errorInfo = saveErrorInfo;
9485-
return result;
9486-
}
9487-
}
9488-
}
94899487
}
94909488
else if (source.flags & TypeFlags.IndexedAccess) {
94919489
// A type S[K] is related to a type T if A[K] is related to T, where K is string-like and

tests/baselines/reference/mappedTypeRelationships.errors.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,4 +460,16 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
460460
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
461461
!!! error TS2322: Type 'T' is not assignable to type 'U'.
462462
}
463+
464+
function f80<T>(t: T): Partial<T> {
465+
return t;
466+
}
467+
468+
function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]> {
469+
return t[k];
470+
}
471+
472+
function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]> {
473+
return t[k1][k2];
474+
}
463475

tests/baselines/reference/mappedTypeRelationships.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,18 @@ function f76<T, U extends T, K extends keyof T>(x: { [P in K]: T[P] }, y: { [P i
168168
x = y;
169169
y = x; // Error
170170
}
171+
172+
function f80<T>(t: T): Partial<T> {
173+
return t;
174+
}
175+
176+
function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]> {
177+
return t[k];
178+
}
179+
180+
function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]> {
181+
return t[k1][k2];
182+
}
171183

172184

173185
//// [mappedTypeRelationships.js]
@@ -289,6 +301,15 @@ function f76(x, y) {
289301
x = y;
290302
y = x; // Error
291303
}
304+
function f80(t) {
305+
return t;
306+
}
307+
function f81(t, k) {
308+
return t[k];
309+
}
310+
function f82(t, k1, k2) {
311+
return t[k1][k2];
312+
}
292313

293314

294315
//// [mappedTypeRelationships.d.ts]
@@ -369,3 +390,6 @@ declare function f76<T, U extends T, K extends keyof T>(x: {
369390
}, y: {
370391
[P in K]: U[P];
371392
}): void;
393+
declare function f80<T>(t: T): Partial<T>;
394+
declare function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]>;
395+
declare function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]>;

tests/baselines/reference/mappedTypeRelationships.symbols

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,3 +750,58 @@ function f76<T, U extends T, K extends keyof T>(x: { [P in K]: T[P] }, y: { [P i
750750
>x : Symbol(x, Decl(mappedTypeRelationships.ts, 165, 48))
751751
}
752752

753+
function f80<T>(t: T): Partial<T> {
754+
>f80 : Symbol(f80, Decl(mappedTypeRelationships.ts, 168, 1))
755+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 170, 13))
756+
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 170, 16))
757+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 170, 13))
758+
>Partial : Symbol(Partial, Decl(lib.d.ts, --, --))
759+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 170, 13))
760+
761+
return t;
762+
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 170, 16))
763+
}
764+
765+
function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]> {
766+
>f81 : Symbol(f81, Decl(mappedTypeRelationships.ts, 172, 1))
767+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 174, 13))
768+
>K : Symbol(K, Decl(mappedTypeRelationships.ts, 174, 15))
769+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 174, 13))
770+
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 174, 35))
771+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 174, 13))
772+
>k : Symbol(k, Decl(mappedTypeRelationships.ts, 174, 40))
773+
>K : Symbol(K, Decl(mappedTypeRelationships.ts, 174, 15))
774+
>Partial : Symbol(Partial, Decl(lib.d.ts, --, --))
775+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 174, 13))
776+
>K : Symbol(K, Decl(mappedTypeRelationships.ts, 174, 15))
777+
778+
return t[k];
779+
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 174, 35))
780+
>k : Symbol(k, Decl(mappedTypeRelationships.ts, 174, 40))
781+
}
782+
783+
function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]> {
784+
>f82 : Symbol(f82, Decl(mappedTypeRelationships.ts, 176, 1))
785+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 178, 13))
786+
>K1 : Symbol(K1, Decl(mappedTypeRelationships.ts, 178, 15))
787+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 178, 13))
788+
>K2 : Symbol(K2, Decl(mappedTypeRelationships.ts, 178, 35))
789+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 178, 13))
790+
>K1 : Symbol(K1, Decl(mappedTypeRelationships.ts, 178, 15))
791+
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 178, 60))
792+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 178, 13))
793+
>k1 : Symbol(k1, Decl(mappedTypeRelationships.ts, 178, 65))
794+
>K1 : Symbol(K1, Decl(mappedTypeRelationships.ts, 178, 15))
795+
>k2 : Symbol(k2, Decl(mappedTypeRelationships.ts, 178, 73))
796+
>K2 : Symbol(K2, Decl(mappedTypeRelationships.ts, 178, 35))
797+
>Partial : Symbol(Partial, Decl(lib.d.ts, --, --))
798+
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 178, 13))
799+
>K1 : Symbol(K1, Decl(mappedTypeRelationships.ts, 178, 15))
800+
>K2 : Symbol(K2, Decl(mappedTypeRelationships.ts, 178, 35))
801+
802+
return t[k1][k2];
803+
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 178, 60))
804+
>k1 : Symbol(k1, Decl(mappedTypeRelationships.ts, 178, 65))
805+
>k2 : Symbol(k2, Decl(mappedTypeRelationships.ts, 178, 73))
806+
}
807+

tests/baselines/reference/mappedTypeRelationships.types

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,3 +856,61 @@ function f76<T, U extends T, K extends keyof T>(x: { [P in K]: T[P] }, y: { [P i
856856
>x : { [P in K]: T[P]; }
857857
}
858858

859+
function f80<T>(t: T): Partial<T> {
860+
>f80 : <T>(t: T) => Partial<T>
861+
>T : T
862+
>t : T
863+
>T : T
864+
>Partial : Partial<T>
865+
>T : T
866+
867+
return t;
868+
>t : T
869+
}
870+
871+
function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]> {
872+
>f81 : <T, K extends keyof T>(t: T, k: K) => Partial<T[K]>
873+
>T : T
874+
>K : K
875+
>T : T
876+
>t : T
877+
>T : T
878+
>k : K
879+
>K : K
880+
>Partial : Partial<T>
881+
>T : T
882+
>K : K
883+
884+
return t[k];
885+
>t[k] : T[K]
886+
>t : T
887+
>k : K
888+
}
889+
890+
function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]> {
891+
>f82 : <T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2) => Partial<T[K1][K2]>
892+
>T : T
893+
>K1 : K1
894+
>T : T
895+
>K2 : K2
896+
>T : T
897+
>K1 : K1
898+
>t : T
899+
>T : T
900+
>k1 : K1
901+
>K1 : K1
902+
>k2 : K2
903+
>K2 : K2
904+
>Partial : Partial<T>
905+
>T : T
906+
>K1 : K1
907+
>K2 : K2
908+
909+
return t[k1][k2];
910+
>t[k1][k2] : T[K1][K2]
911+
>t[k1] : T[K1]
912+
>t : T
913+
>k1 : K1
914+
>k2 : K2
915+
}
916+

tests/cases/conformance/types/mapped/mappedTypeRelationships.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,15 @@ function f76<T, U extends T, K extends keyof T>(x: { [P in K]: T[P] }, y: { [P i
170170
x = y;
171171
y = x; // Error
172172
}
173+
174+
function f80<T>(t: T): Partial<T> {
175+
return t;
176+
}
177+
178+
function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]> {
179+
return t[k];
180+
}
181+
182+
function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]> {
183+
return t[k1][k2];
184+
}

0 commit comments

Comments
 (0)