Merge pull request #19564 from Microsoft/fixGenericMappedTypeRelationships

Fix generic mapped type relationships
This commit is contained in:
Anders Hejlsberg 2017-10-30 12:42:24 -07:00 committed by GitHub
commit 7f4a132af9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 179 additions and 20 deletions

View file

@ -9460,32 +9460,30 @@ namespace ts {
}
}
}
else if (isGenericMappedType(target) && !isGenericMappedType(source) && getConstraintTypeFromMappedType(<MappedType>target) === getIndexType(source)) {
// A source type T is related to a target type { [P in keyof T]: X } if T[P] is related to X.
const indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(<MappedType>target));
const templateType = getTemplateTypeFromMappedType(<MappedType>target);
if (result = isRelatedTo(indexedAccessType, templateType, reportErrors)) {
errorInfo = saveErrorInfo;
return result;
}
}
if (source.flags & TypeFlags.TypeParameter) {
// A source type T is related to a target type { [P in keyof T]: X } if T[P] is related to X.
if (getObjectFlags(target) & ObjectFlags.Mapped && getConstraintTypeFromMappedType(<MappedType>target) === getIndexType(source)) {
const indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(<MappedType>target));
const templateType = getTemplateTypeFromMappedType(<MappedType>target);
if (result = isRelatedTo(indexedAccessType, templateType, reportErrors)) {
let constraint = getConstraintOfTypeParameter(<TypeParameter>source);
// A type parameter with no constraint is not related to the non-primitive object type.
if (constraint || !(target.flags & TypeFlags.NonPrimitive)) {
if (!constraint || constraint.flags & TypeFlags.Any) {
constraint = emptyObjectType;
}
// Report constraint errors only if the constraint is not the empty object type
const reportConstraintErrors = reportErrors && constraint !== emptyObjectType;
if (result = isRelatedTo(constraint, target, reportConstraintErrors)) {
errorInfo = saveErrorInfo;
return result;
}
}
else {
let constraint = getConstraintOfTypeParameter(<TypeParameter>source);
// A type parameter with no constraint is not related to the non-primitive object type.
if (constraint || !(target.flags & TypeFlags.NonPrimitive)) {
if (!constraint || constraint.flags & TypeFlags.Any) {
constraint = emptyObjectType;
}
// Report constraint errors only if the constraint is not the empty object type
const reportConstraintErrors = reportErrors && constraint !== emptyObjectType;
if (result = isRelatedTo(constraint, target, reportConstraintErrors)) {
errorInfo = saveErrorInfo;
return result;
}
}
}
}
else if (source.flags & TypeFlags.IndexedAccess) {
// A type S[K] is related to a type T if A[K] is related to T, where K is string-like and

View file

@ -460,4 +460,16 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
function f80<T>(t: T): Partial<T> {
return t;
}
function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]> {
return t[k];
}
function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]> {
return t[k1][k2];
}

View file

@ -168,6 +168,18 @@ function f76<T, U extends T, K extends keyof T>(x: { [P in K]: T[P] }, y: { [P i
x = y;
y = x; // Error
}
function f80<T>(t: T): Partial<T> {
return t;
}
function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]> {
return t[k];
}
function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]> {
return t[k1][k2];
}
//// [mappedTypeRelationships.js]
@ -289,6 +301,15 @@ function f76(x, y) {
x = y;
y = x; // Error
}
function f80(t) {
return t;
}
function f81(t, k) {
return t[k];
}
function f82(t, k1, k2) {
return t[k1][k2];
}
//// [mappedTypeRelationships.d.ts]
@ -369,3 +390,6 @@ declare function f76<T, U extends T, K extends keyof T>(x: {
}, y: {
[P in K]: U[P];
}): void;
declare function f80<T>(t: T): Partial<T>;
declare function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]>;
declare function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]>;

View file

@ -750,3 +750,58 @@ function f76<T, U extends T, K extends keyof T>(x: { [P in K]: T[P] }, y: { [P i
>x : Symbol(x, Decl(mappedTypeRelationships.ts, 165, 48))
}
function f80<T>(t: T): Partial<T> {
>f80 : Symbol(f80, Decl(mappedTypeRelationships.ts, 168, 1))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 170, 13))
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 170, 16))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 170, 13))
>Partial : Symbol(Partial, Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 170, 13))
return t;
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 170, 16))
}
function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]> {
>f81 : Symbol(f81, Decl(mappedTypeRelationships.ts, 172, 1))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 174, 13))
>K : Symbol(K, Decl(mappedTypeRelationships.ts, 174, 15))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 174, 13))
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 174, 35))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 174, 13))
>k : Symbol(k, Decl(mappedTypeRelationships.ts, 174, 40))
>K : Symbol(K, Decl(mappedTypeRelationships.ts, 174, 15))
>Partial : Symbol(Partial, Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 174, 13))
>K : Symbol(K, Decl(mappedTypeRelationships.ts, 174, 15))
return t[k];
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 174, 35))
>k : Symbol(k, Decl(mappedTypeRelationships.ts, 174, 40))
}
function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]> {
>f82 : Symbol(f82, Decl(mappedTypeRelationships.ts, 176, 1))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 178, 13))
>K1 : Symbol(K1, Decl(mappedTypeRelationships.ts, 178, 15))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 178, 13))
>K2 : Symbol(K2, Decl(mappedTypeRelationships.ts, 178, 35))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 178, 13))
>K1 : Symbol(K1, Decl(mappedTypeRelationships.ts, 178, 15))
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 178, 60))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 178, 13))
>k1 : Symbol(k1, Decl(mappedTypeRelationships.ts, 178, 65))
>K1 : Symbol(K1, Decl(mappedTypeRelationships.ts, 178, 15))
>k2 : Symbol(k2, Decl(mappedTypeRelationships.ts, 178, 73))
>K2 : Symbol(K2, Decl(mappedTypeRelationships.ts, 178, 35))
>Partial : Symbol(Partial, Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(mappedTypeRelationships.ts, 178, 13))
>K1 : Symbol(K1, Decl(mappedTypeRelationships.ts, 178, 15))
>K2 : Symbol(K2, Decl(mappedTypeRelationships.ts, 178, 35))
return t[k1][k2];
>t : Symbol(t, Decl(mappedTypeRelationships.ts, 178, 60))
>k1 : Symbol(k1, Decl(mappedTypeRelationships.ts, 178, 65))
>k2 : Symbol(k2, Decl(mappedTypeRelationships.ts, 178, 73))
}

View file

@ -856,3 +856,61 @@ function f76<T, U extends T, K extends keyof T>(x: { [P in K]: T[P] }, y: { [P i
>x : { [P in K]: T[P]; }
}
function f80<T>(t: T): Partial<T> {
>f80 : <T>(t: T) => Partial<T>
>T : T
>t : T
>T : T
>Partial : Partial<T>
>T : T
return t;
>t : T
}
function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]> {
>f81 : <T, K extends keyof T>(t: T, k: K) => Partial<T[K]>
>T : T
>K : K
>T : T
>t : T
>T : T
>k : K
>K : K
>Partial : Partial<T>
>T : T
>K : K
return t[k];
>t[k] : T[K]
>t : T
>k : K
}
function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]> {
>f82 : <T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2) => Partial<T[K1][K2]>
>T : T
>K1 : K1
>T : T
>K2 : K2
>T : T
>K1 : K1
>t : T
>T : T
>k1 : K1
>K1 : K1
>k2 : K2
>K2 : K2
>Partial : Partial<T>
>T : T
>K1 : K1
>K2 : K2
return t[k1][k2];
>t[k1][k2] : T[K1][K2]
>t[k1] : T[K1]
>t : T
>k1 : K1
>k2 : K2
}

View file

@ -170,3 +170,15 @@ function f76<T, U extends T, K extends keyof T>(x: { [P in K]: T[P] }, y: { [P i
x = y;
y = x; // Error
}
function f80<T>(t: T): Partial<T> {
return t;
}
function f81<T, K extends keyof T>(t: T, k: K): Partial<T[K]> {
return t[k];
}
function f82<T, K1 extends keyof T, K2 extends keyof T[K1]>(t: T, k1: K1, k2: K2): Partial<T[K1][K2]> {
return t[k1][k2];
}