Merge pull request #13061 from Microsoft/fixMappedTypeConstraint

Fix mapped type constraint checking
This commit is contained in:
Anders Hejlsberg 2016-12-20 08:51:10 -10:00 committed by GitHub
commit f3ad09a6f6
4 changed files with 72 additions and 6 deletions

View File

@ -4612,8 +4612,8 @@ namespace ts {
// the modifiers type is T. Otherwise, the modifiers type is {}.
const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
const constraint = getConstraintTypeFromMappedType(declaredType);
const extendedConstraint = constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
type.modifiersType = extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
const extendedConstraint = constraint && constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
type.modifiersType = extendedConstraint && extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
}
}
return type.modifiersType;

View File

@ -45,9 +45,11 @@ tests/cases/conformance/types/mapped/mappedTypeErrors.ts(130,5): error TS2322: T
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(131,5): error TS2322: Type '{ a: string; }' is not assignable to type '{ [x: string]: any; a?: number | undefined; }'.
Types of property 'a' are incompatible.
Type 'string' is not assignable to type 'number | undefined'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(137,16): error TS2322: Type '{}' is not assignable to type 'string'.
tests/cases/conformance/types/mapped/mappedTypeErrors.ts(137,21): error TS2536: Type 'P' cannot be used to index type 'T'.
==== tests/cases/conformance/types/mapped/mappedTypeErrors.ts (24 errors) ====
==== tests/cases/conformance/types/mapped/mappedTypeErrors.ts (26 errors) ====
interface Shape {
name: string;
@ -249,4 +251,22 @@ tests/cases/conformance/types/mapped/mappedTypeErrors.ts(131,5): error TS2322: T
~~
!!! error TS2322: Type '{ a: string; }' is not assignable to type '{ [x: string]: any; a?: number | undefined; }'.
!!! error TS2322: Types of property 'a' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type 'number | undefined'.
!!! error TS2322: Type 'string' is not assignable to type 'number | undefined'.
// Repro from #13044
type Foo2<T, F extends keyof T> = {
pf: {[P in F]?: T[P]},
pt: {[P in T]?: T[P]}, // note: should be in keyof T
~
!!! error TS2322: Type '{}' is not assignable to type 'string'.
~~~~
!!! error TS2536: Type 'P' cannot be used to index type 'T'.
};
type O = {x: number, y: boolean};
let o: O = {x: 5, y: false};
let f: Foo2<O, 'x'> = {
pf: {x: 7},
pt: {x: 7, y: false},
};

View File

@ -129,7 +129,21 @@ type T2 = { a?: number, [key: string]: any };
let x1: T2 = { a: 'no' }; // Error
let x2: Partial<T2> = { a: 'no' }; // Error
let x3: { [P in keyof T2]: T2[P]} = { a: 'no' }; // Error
let x3: { [P in keyof T2]: T2[P]} = { a: 'no' }; // Error
// Repro from #13044
type Foo2<T, F extends keyof T> = {
pf: {[P in F]?: T[P]},
pt: {[P in T]?: T[P]}, // note: should be in keyof T
};
type O = {x: number, y: boolean};
let o: O = {x: 5, y: false};
let f: Foo2<O, 'x'> = {
pf: {x: 7},
pt: {x: 7, y: false},
};
//// [mappedTypeErrors.js]
function f1(x) {
@ -204,6 +218,11 @@ c.setState({ c: true }); // Error
var x1 = { a: 'no' }; // Error
var x2 = { a: 'no' }; // Error
var x3 = { a: 'no' }; // Error
var o = { x: 5, y: false };
var f = {
pf: { x: 7 },
pt: { x: 7, y: false }
};
//// [mappedTypeErrors.d.ts]
@ -268,3 +287,17 @@ declare let x2: Partial<T2>;
declare let x3: {
[P in keyof T2]: T2[P];
};
declare type Foo2<T, F extends keyof T> = {
pf: {
[P in F]?: T[P];
};
pt: {
[P in T]?: T[P];
};
};
declare type O = {
x: number;
y: boolean;
};
declare let o: O;
declare let f: Foo2<O, 'x'>;

View File

@ -130,4 +130,17 @@ type T2 = { a?: number, [key: string]: any };
let x1: T2 = { a: 'no' }; // Error
let x2: Partial<T2> = { a: 'no' }; // Error
let x3: { [P in keyof T2]: T2[P]} = { a: 'no' }; // Error
let x3: { [P in keyof T2]: T2[P]} = { a: 'no' }; // Error
// Repro from #13044
type Foo2<T, F extends keyof T> = {
pf: {[P in F]?: T[P]},
pt: {[P in T]?: T[P]}, // note: should be in keyof T
};
type O = {x: number, y: boolean};
let o: O = {x: 5, y: false};
let f: Foo2<O, 'x'> = {
pf: {x: 7},
pt: {x: 7, y: false},
};