From f55b3ef87a8263c44ab41d728c4669363dfa772c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 29 Nov 2016 12:48:41 -0800 Subject: [PATCH 1/3] Preserve modifiers in isomorphic mapped types --- src/compiler/checker.ts | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 527735a3b0f4a..46f10488779e6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4497,12 +4497,14 @@ namespace ts { // Resolve upfront such that recursive references see an empty object type. setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, undefined, undefined); // In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type, - // and T as the template type. + // and T as the template type. If K is of the form 'keyof S', the mapped type and S are + // isomorphic and we copy property modifiers from corresponding properties in S. const typeParameter = getTypeParameterFromMappedType(type); const constraintType = getConstraintTypeFromMappedType(type); + const isomorphicType = getIsomorphicTypeFromMappedType(type); const templateType = getTemplateTypeFromMappedType(type); - const isReadonly = !!type.declaration.readonlyToken; - const isOptional = !!type.declaration.questionToken; + const templateReadonly = !!type.declaration.readonlyToken; + const templateOptional = !!type.declaration.questionToken; // First, if the constraint type is a type parameter, obtain the base constraint. Then, // if the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X. // Finally, iterate over the constituents of the resulting iteration type. @@ -4515,18 +4517,19 @@ namespace ts { const iterationMapper = createUnaryTypeMapper(typeParameter, t); const templateMapper = type.mapper ? combineTypeMappers(type.mapper, iterationMapper) : iterationMapper; const propType = instantiateType(templateType, templateMapper); - // If the current iteration type constituent is a literal type, create a property. - // Otherwise, for type string create a string index signature and for type number - // create a numeric index signature. - if (t.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral | TypeFlags.EnumLiteral)) { + // If the current iteration type constituent is a string literal type, create a property. + // Otherwise, for type string create a string index signature. + if (t.flags & TypeFlags.StringLiteral) { const propName = (t).text; + const isomorphicProp = isomorphicType && getPropertyOfType(isomorphicType, propName); + const isOptional = templateOptional || !!(isomorphicProp && isomorphicProp.flags & SymbolFlags.Optional); const prop = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | (isOptional ? SymbolFlags.Optional : 0), propName); prop.type = addOptionality(propType, isOptional); - prop.isReadonly = isReadonly; + prop.isReadonly = templateReadonly || isomorphicProp && isReadonlySymbol(isomorphicProp); members[propName] = prop; } else if (t.flags & TypeFlags.String) { - stringIndexInfo = createIndexInfo(propType, isReadonly); + stringIndexInfo = createIndexInfo(propType, templateReadonly); } }); setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined); @@ -4549,6 +4552,11 @@ namespace ts { unknownType); } + function getIsomorphicTypeFromMappedType(type: MappedType) { + const constraint = getConstraintDeclaration(getTypeParameterFromMappedType(type)); + return constraint.kind === SyntaxKind.TypeOperator ? instantiateType(getTypeFromTypeNode((constraint).type), type.mapper || identityMapper) : undefined; + } + function getErasedTemplateTypeFromMappedType(type: MappedType) { return instantiateType(getTemplateTypeFromMappedType(type), createUnaryTypeMapper(getTypeParameterFromMappedType(type), anyType)); } From f366ae0332425a3c031d71580d5d5406f92efdb1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 29 Nov 2016 12:48:55 -0800 Subject: [PATCH 2/3] Add tests --- .../reference/mappedTypeModifiers.js | 73 +++++++++ .../reference/mappedTypeModifiers.symbols | 148 ++++++++++++++++++ .../reference/mappedTypeModifiers.types | 148 ++++++++++++++++++ .../types/mapped/mappedTypeModifiers.ts | 42 +++++ 4 files changed, 411 insertions(+) create mode 100644 tests/baselines/reference/mappedTypeModifiers.js create mode 100644 tests/baselines/reference/mappedTypeModifiers.symbols create mode 100644 tests/baselines/reference/mappedTypeModifiers.types create mode 100644 tests/cases/conformance/types/mapped/mappedTypeModifiers.ts diff --git a/tests/baselines/reference/mappedTypeModifiers.js b/tests/baselines/reference/mappedTypeModifiers.js new file mode 100644 index 0000000000000..8f3f7ba5416a5 --- /dev/null +++ b/tests/baselines/reference/mappedTypeModifiers.js @@ -0,0 +1,73 @@ +//// [mappedTypeModifiers.ts] + +type T = { a: number, b: string }; +type U = { a: number | undefined, b: string | undefined }; +type P = { a?: number, b?: string }; +type R = { readonly a: number, readonly b: string }; +type PR = { readonly a?: number, readonly b?: string }; + +// Validate they all have the same keys +var v00: "a" | "b"; +var v00: keyof T; +var v00: keyof U; +var v00: keyof P; +var v00: keyof R; +var v00: keyof PR; + +// Validate that non-isomorphic mapped types strip modifiers +var v01: T; +var v01: Pick; +var v01: Pick, keyof T>; + +// Validate that non-isomorphic mapped types strip modifiers +var v02: U; +var v02: Pick; +var v02: Pick; +var v02: Pick, keyof T>; +var v02: Pick>, keyof T>; + +// Validate that isomorphic mapped types preserve optional modifier +var v03: P; +var v03: Partial; + +// Validate that isomorphic mapped types preserve readonly modifier +var v04: R; +var v04: Readonly; + +// Validate that isomorphic mapped types preserve both partial and readonly modifiers +var v05: PR; +var v05: Partial; +var v05: Readonly

; +var v05: Partial>; +var v05: Readonly>; + +//// [mappedTypeModifiers.js] +// Validate they all have the same keys +var v00; +var v00; +var v00; +var v00; +var v00; +var v00; +// Validate that non-isomorphic mapped types strip modifiers +var v01; +var v01; +var v01; +// Validate that non-isomorphic mapped types strip modifiers +var v02; +var v02; +var v02; +var v02; +var v02; +// Validate that isomorphic mapped types preserve optional modifier +var v03; +var v03; +// Validate that isomorphic mapped types preserve readonly modifier +var v04; +var v04; +// Validate that isomorphic mapped types preserve both partial and readonly modifiers +var v05; +var v05; +var v05; +var v05; +var v05; diff --git a/tests/baselines/reference/mappedTypeModifiers.symbols b/tests/baselines/reference/mappedTypeModifiers.symbols new file mode 100644 index 0000000000000..6799d13d1acd5 --- /dev/null +++ b/tests/baselines/reference/mappedTypeModifiers.symbols @@ -0,0 +1,148 @@ +=== tests/cases/conformance/types/mapped/mappedTypeModifiers.ts === + +type T = { a: number, b: string }; +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 1, 10)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 1, 21)) + +type U = { a: number | undefined, b: string | undefined }; +>U : Symbol(U, Decl(mappedTypeModifiers.ts, 1, 34)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 2, 10)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 2, 33)) + +type P = { a?: number, b?: string }; +>P : Symbol(P, Decl(mappedTypeModifiers.ts, 2, 58)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 3, 10)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 3, 22)) + +type R = { readonly a: number, readonly b: string }; +>R : Symbol(R, Decl(mappedTypeModifiers.ts, 3, 36)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 4, 10)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 4, 30)) + +type PR = { readonly a?: number, readonly b?: string }; +>PR : Symbol(PR, Decl(mappedTypeModifiers.ts, 4, 52)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 5, 11)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 5, 32)) + +// Validate they all have the same keys +var v00: "a" | "b"; +>v00 : Symbol(v00, Decl(mappedTypeModifiers.ts, 8, 3), Decl(mappedTypeModifiers.ts, 9, 3), Decl(mappedTypeModifiers.ts, 10, 3), Decl(mappedTypeModifiers.ts, 11, 3), Decl(mappedTypeModifiers.ts, 12, 3), Decl(mappedTypeModifiers.ts, 13, 3)) + +var v00: keyof T; +>v00 : Symbol(v00, Decl(mappedTypeModifiers.ts, 8, 3), Decl(mappedTypeModifiers.ts, 9, 3), Decl(mappedTypeModifiers.ts, 10, 3), Decl(mappedTypeModifiers.ts, 11, 3), Decl(mappedTypeModifiers.ts, 12, 3), Decl(mappedTypeModifiers.ts, 13, 3)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + +var v00: keyof U; +>v00 : Symbol(v00, Decl(mappedTypeModifiers.ts, 8, 3), Decl(mappedTypeModifiers.ts, 9, 3), Decl(mappedTypeModifiers.ts, 10, 3), Decl(mappedTypeModifiers.ts, 11, 3), Decl(mappedTypeModifiers.ts, 12, 3), Decl(mappedTypeModifiers.ts, 13, 3)) +>U : Symbol(U, Decl(mappedTypeModifiers.ts, 1, 34)) + +var v00: keyof P; +>v00 : Symbol(v00, Decl(mappedTypeModifiers.ts, 8, 3), Decl(mappedTypeModifiers.ts, 9, 3), Decl(mappedTypeModifiers.ts, 10, 3), Decl(mappedTypeModifiers.ts, 11, 3), Decl(mappedTypeModifiers.ts, 12, 3), Decl(mappedTypeModifiers.ts, 13, 3)) +>P : Symbol(P, Decl(mappedTypeModifiers.ts, 2, 58)) + +var v00: keyof R; +>v00 : Symbol(v00, Decl(mappedTypeModifiers.ts, 8, 3), Decl(mappedTypeModifiers.ts, 9, 3), Decl(mappedTypeModifiers.ts, 10, 3), Decl(mappedTypeModifiers.ts, 11, 3), Decl(mappedTypeModifiers.ts, 12, 3), Decl(mappedTypeModifiers.ts, 13, 3)) +>R : Symbol(R, Decl(mappedTypeModifiers.ts, 3, 36)) + +var v00: keyof PR; +>v00 : Symbol(v00, Decl(mappedTypeModifiers.ts, 8, 3), Decl(mappedTypeModifiers.ts, 9, 3), Decl(mappedTypeModifiers.ts, 10, 3), Decl(mappedTypeModifiers.ts, 11, 3), Decl(mappedTypeModifiers.ts, 12, 3), Decl(mappedTypeModifiers.ts, 13, 3)) +>PR : Symbol(PR, Decl(mappedTypeModifiers.ts, 4, 52)) + +// Validate that non-isomorphic mapped types strip modifiers +var v01: T; +>v01 : Symbol(v01, Decl(mappedTypeModifiers.ts, 16, 3), Decl(mappedTypeModifiers.ts, 17, 3), Decl(mappedTypeModifiers.ts, 18, 3)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + +var v01: Pick; +>v01 : Symbol(v01, Decl(mappedTypeModifiers.ts, 16, 3), Decl(mappedTypeModifiers.ts, 17, 3), Decl(mappedTypeModifiers.ts, 18, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>R : Symbol(R, Decl(mappedTypeModifiers.ts, 3, 36)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + +var v01: Pick, keyof T>; +>v01 : Symbol(v01, Decl(mappedTypeModifiers.ts, 16, 3), Decl(mappedTypeModifiers.ts, 17, 3), Decl(mappedTypeModifiers.ts, 18, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + +// Validate that non-isomorphic mapped types strip modifiers +var v02: U; +>v02 : Symbol(v02, Decl(mappedTypeModifiers.ts, 21, 3), Decl(mappedTypeModifiers.ts, 22, 3), Decl(mappedTypeModifiers.ts, 23, 3), Decl(mappedTypeModifiers.ts, 24, 3), Decl(mappedTypeModifiers.ts, 25, 3)) +>U : Symbol(U, Decl(mappedTypeModifiers.ts, 1, 34)) + +var v02: Pick; +>v02 : Symbol(v02, Decl(mappedTypeModifiers.ts, 21, 3), Decl(mappedTypeModifiers.ts, 22, 3), Decl(mappedTypeModifiers.ts, 23, 3), Decl(mappedTypeModifiers.ts, 24, 3), Decl(mappedTypeModifiers.ts, 25, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>P : Symbol(P, Decl(mappedTypeModifiers.ts, 2, 58)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + +var v02: Pick; +>v02 : Symbol(v02, Decl(mappedTypeModifiers.ts, 21, 3), Decl(mappedTypeModifiers.ts, 22, 3), Decl(mappedTypeModifiers.ts, 23, 3), Decl(mappedTypeModifiers.ts, 24, 3), Decl(mappedTypeModifiers.ts, 25, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>PR : Symbol(PR, Decl(mappedTypeModifiers.ts, 4, 52)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + +var v02: Pick, keyof T>; +>v02 : Symbol(v02, Decl(mappedTypeModifiers.ts, 21, 3), Decl(mappedTypeModifiers.ts, 22, 3), Decl(mappedTypeModifiers.ts, 23, 3), Decl(mappedTypeModifiers.ts, 24, 3), Decl(mappedTypeModifiers.ts, 25, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + +var v02: Pick>, keyof T>; +>v02 : Symbol(v02, Decl(mappedTypeModifiers.ts, 21, 3), Decl(mappedTypeModifiers.ts, 22, 3), Decl(mappedTypeModifiers.ts, 23, 3), Decl(mappedTypeModifiers.ts, 24, 3), Decl(mappedTypeModifiers.ts, 25, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + +// Validate that isomorphic mapped types preserve optional modifier +var v03: P; +>v03 : Symbol(v03, Decl(mappedTypeModifiers.ts, 28, 3), Decl(mappedTypeModifiers.ts, 29, 3)) +>P : Symbol(P, Decl(mappedTypeModifiers.ts, 2, 58)) + +var v03: Partial; +>v03 : Symbol(v03, Decl(mappedTypeModifiers.ts, 28, 3), Decl(mappedTypeModifiers.ts, 29, 3)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + +// Validate that isomorphic mapped types preserve readonly modifier +var v04: R; +>v04 : Symbol(v04, Decl(mappedTypeModifiers.ts, 32, 3), Decl(mappedTypeModifiers.ts, 33, 3)) +>R : Symbol(R, Decl(mappedTypeModifiers.ts, 3, 36)) + +var v04: Readonly; +>v04 : Symbol(v04, Decl(mappedTypeModifiers.ts, 32, 3), Decl(mappedTypeModifiers.ts, 33, 3)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + +// Validate that isomorphic mapped types preserve both partial and readonly modifiers +var v05: PR; +>v05 : Symbol(v05, Decl(mappedTypeModifiers.ts, 36, 3), Decl(mappedTypeModifiers.ts, 37, 3), Decl(mappedTypeModifiers.ts, 38, 3), Decl(mappedTypeModifiers.ts, 39, 3), Decl(mappedTypeModifiers.ts, 40, 3)) +>PR : Symbol(PR, Decl(mappedTypeModifiers.ts, 4, 52)) + +var v05: Partial; +>v05 : Symbol(v05, Decl(mappedTypeModifiers.ts, 36, 3), Decl(mappedTypeModifiers.ts, 37, 3), Decl(mappedTypeModifiers.ts, 38, 3), Decl(mappedTypeModifiers.ts, 39, 3), Decl(mappedTypeModifiers.ts, 40, 3)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>R : Symbol(R, Decl(mappedTypeModifiers.ts, 3, 36)) + +var v05: Readonly

; +>v05 : Symbol(v05, Decl(mappedTypeModifiers.ts, 36, 3), Decl(mappedTypeModifiers.ts, 37, 3), Decl(mappedTypeModifiers.ts, 38, 3), Decl(mappedTypeModifiers.ts, 39, 3), Decl(mappedTypeModifiers.ts, 40, 3)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>P : Symbol(P, Decl(mappedTypeModifiers.ts, 2, 58)) + +var v05: Partial>; +>v05 : Symbol(v05, Decl(mappedTypeModifiers.ts, 36, 3), Decl(mappedTypeModifiers.ts, 37, 3), Decl(mappedTypeModifiers.ts, 38, 3), Decl(mappedTypeModifiers.ts, 39, 3), Decl(mappedTypeModifiers.ts, 40, 3)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + +var v05: Readonly>; +>v05 : Symbol(v05, Decl(mappedTypeModifiers.ts, 36, 3), Decl(mappedTypeModifiers.ts, 37, 3), Decl(mappedTypeModifiers.ts, 38, 3), Decl(mappedTypeModifiers.ts, 39, 3), Decl(mappedTypeModifiers.ts, 40, 3)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) + diff --git a/tests/baselines/reference/mappedTypeModifiers.types b/tests/baselines/reference/mappedTypeModifiers.types new file mode 100644 index 0000000000000..5c713991f7539 --- /dev/null +++ b/tests/baselines/reference/mappedTypeModifiers.types @@ -0,0 +1,148 @@ +=== tests/cases/conformance/types/mapped/mappedTypeModifiers.ts === + +type T = { a: number, b: string }; +>T : T +>a : number +>b : string + +type U = { a: number | undefined, b: string | undefined }; +>U : U +>a : number | undefined +>b : string | undefined + +type P = { a?: number, b?: string }; +>P : P +>a : number | undefined +>b : string | undefined + +type R = { readonly a: number, readonly b: string }; +>R : R +>a : number +>b : string + +type PR = { readonly a?: number, readonly b?: string }; +>PR : PR +>a : number | undefined +>b : string | undefined + +// Validate they all have the same keys +var v00: "a" | "b"; +>v00 : "a" | "b" + +var v00: keyof T; +>v00 : "a" | "b" +>T : T + +var v00: keyof U; +>v00 : "a" | "b" +>U : U + +var v00: keyof P; +>v00 : "a" | "b" +>P : P + +var v00: keyof R; +>v00 : "a" | "b" +>R : R + +var v00: keyof PR; +>v00 : "a" | "b" +>PR : PR + +// Validate that non-isomorphic mapped types strip modifiers +var v01: T; +>v01 : T +>T : T + +var v01: Pick; +>v01 : T +>Pick : Pick +>R : R +>T : T + +var v01: Pick, keyof T>; +>v01 : T +>Pick : Pick +>Readonly : Readonly +>T : T +>T : T + +// Validate that non-isomorphic mapped types strip modifiers +var v02: U; +>v02 : U +>U : U + +var v02: Pick; +>v02 : U +>Pick : Pick +>P : P +>T : T + +var v02: Pick; +>v02 : U +>Pick : Pick +>PR : PR +>T : T + +var v02: Pick, keyof T>; +>v02 : U +>Pick : Pick +>Partial : Partial +>T : T +>T : T + +var v02: Pick>, keyof T>; +>v02 : U +>Pick : Pick +>Partial : Partial +>Readonly : Readonly +>T : T +>T : T + +// Validate that isomorphic mapped types preserve optional modifier +var v03: P; +>v03 : P +>P : P + +var v03: Partial; +>v03 : P +>Partial : Partial +>T : T + +// Validate that isomorphic mapped types preserve readonly modifier +var v04: R; +>v04 : R +>R : R + +var v04: Readonly; +>v04 : R +>Readonly : Readonly +>T : T + +// Validate that isomorphic mapped types preserve both partial and readonly modifiers +var v05: PR; +>v05 : PR +>PR : PR + +var v05: Partial; +>v05 : PR +>Partial : Partial +>R : R + +var v05: Readonly

; +>v05 : PR +>Readonly : Readonly +>P : P + +var v05: Partial>; +>v05 : PR +>Partial : Partial +>Readonly : Readonly +>T : T + +var v05: Readonly>; +>v05 : PR +>Readonly : Readonly +>Partial : Partial +>T : T + diff --git a/tests/cases/conformance/types/mapped/mappedTypeModifiers.ts b/tests/cases/conformance/types/mapped/mappedTypeModifiers.ts new file mode 100644 index 0000000000000..947f0c579a1c8 --- /dev/null +++ b/tests/cases/conformance/types/mapped/mappedTypeModifiers.ts @@ -0,0 +1,42 @@ +// @strictNullChecks: true + +type T = { a: number, b: string }; +type U = { a: number | undefined, b: string | undefined }; +type P = { a?: number, b?: string }; +type R = { readonly a: number, readonly b: string }; +type PR = { readonly a?: number, readonly b?: string }; + +// Validate they all have the same keys +var v00: "a" | "b"; +var v00: keyof T; +var v00: keyof U; +var v00: keyof P; +var v00: keyof R; +var v00: keyof PR; + +// Validate that non-isomorphic mapped types strip modifiers +var v01: T; +var v01: Pick; +var v01: Pick, keyof T>; + +// Validate that non-isomorphic mapped types strip modifiers +var v02: U; +var v02: Pick; +var v02: Pick; +var v02: Pick, keyof T>; +var v02: Pick>, keyof T>; + +// Validate that isomorphic mapped types preserve optional modifier +var v03: P; +var v03: Partial; + +// Validate that isomorphic mapped types preserve readonly modifier +var v04: R; +var v04: Readonly; + +// Validate that isomorphic mapped types preserve both partial and readonly modifiers +var v05: PR; +var v05: Partial; +var v05: Readonly

; +var v05: Partial>; +var v05: Readonly>; \ No newline at end of file From 65e98c84d59bb90f450c5c58949cc47d33cdfb0c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 29 Nov 2016 14:06:10 -0800 Subject: [PATCH 3/3] Add more tests --- .../reference/mappedTypeModifiers.js | 108 ++++++-- .../reference/mappedTypeModifiers.symbols | 255 ++++++++++++++--- .../reference/mappedTypeModifiers.types | 261 ++++++++++++++---- .../types/mapped/mappedTypeModifiers.ts | 79 ++++-- 4 files changed, 574 insertions(+), 129 deletions(-) diff --git a/tests/baselines/reference/mappedTypeModifiers.js b/tests/baselines/reference/mappedTypeModifiers.js index 8f3f7ba5416a5..8489194f95a3c 100644 --- a/tests/baselines/reference/mappedTypeModifiers.js +++ b/tests/baselines/reference/mappedTypeModifiers.js @@ -1,45 +1,88 @@ //// [mappedTypeModifiers.ts] type T = { a: number, b: string }; -type U = { a: number | undefined, b: string | undefined }; -type P = { a?: number, b?: string }; -type R = { readonly a: number, readonly b: string }; -type PR = { readonly a?: number, readonly b?: string }; +type TU = { a: number | undefined, b: string | undefined }; +type TP = { a?: number, b?: string }; +type TR = { readonly a: number, readonly b: string }; +type TPR = { readonly a?: number, readonly b?: string }; // Validate they all have the same keys var v00: "a" | "b"; var v00: keyof T; -var v00: keyof U; -var v00: keyof P; -var v00: keyof R; -var v00: keyof PR; +var v00: keyof TU; +var v00: keyof TP; +var v00: keyof TR; +var v00: keyof TPR; // Validate that non-isomorphic mapped types strip modifiers var v01: T; -var v01: Pick; +var v01: Pick; var v01: Pick, keyof T>; // Validate that non-isomorphic mapped types strip modifiers -var v02: U; -var v02: Pick; -var v02: Pick; +var v02: TU; +var v02: Pick; +var v02: Pick; var v02: Pick, keyof T>; var v02: Pick>, keyof T>; // Validate that isomorphic mapped types preserve optional modifier -var v03: P; +var v03: TP; var v03: Partial; // Validate that isomorphic mapped types preserve readonly modifier -var v04: R; +var v04: TR; var v04: Readonly; // Validate that isomorphic mapped types preserve both partial and readonly modifiers -var v05: PR; -var v05: Partial; -var v05: Readonly

; +var v05: TPR; +var v05: Partial; +var v05: Readonly; var v05: Partial>; -var v05: Readonly>; +var v05: Readonly>; + +type Boxified = { [P in keyof T]: { x: T[P] } }; + +type B = { a: { x: number }, b: { x: string } }; +type BU = { a: { x: number } | undefined, b: { x: string } | undefined }; +type BP = { a?: { x: number }, b?: { x: string } }; +type BR = { readonly a: { x: number }, readonly b: { x: string } }; +type BPR = { readonly a?: { x: number }, readonly b?: { x: string } }; + +// Validate they all have the same keys +var b00: "a" | "b"; +var b00: keyof B; +var b00: keyof BU; +var b00: keyof BP; +var b00: keyof BR; +var b00: keyof BPR; + +// Validate that non-isomorphic mapped types strip modifiers +var b01: B; +var b01: Pick; +var b01: Pick, keyof B>; + +// Validate that non-isomorphic mapped types strip modifiers +var b02: BU; +var b02: Pick; +var b02: Pick; +var b02: Pick, keyof B>; +var b02: Pick>, keyof B>; + +// Validate that isomorphic mapped types preserve optional modifier +var b03: BP; +var b03: Partial; + +// Validate that isomorphic mapped types preserve readonly modifier +var b04: BR; +var b04: Readonly; + +// Validate that isomorphic mapped types preserve both partial and readonly modifiers +var b05: BPR; +var b05: Partial
; +var b05: Readonly; +var b05: Partial>; +var b05: Readonly>; //// [mappedTypeModifiers.js] // Validate they all have the same keys @@ -71,3 +114,32 @@ var v05; var v05; var v05; var v05; +// Validate they all have the same keys +var b00; +var b00; +var b00; +var b00; +var b00; +var b00; +// Validate that non-isomorphic mapped types strip modifiers +var b01; +var b01; +var b01; +// Validate that non-isomorphic mapped types strip modifiers +var b02; +var b02; +var b02; +var b02; +var b02; +// Validate that isomorphic mapped types preserve optional modifier +var b03; +var b03; +// Validate that isomorphic mapped types preserve readonly modifier +var b04; +var b04; +// Validate that isomorphic mapped types preserve both partial and readonly modifiers +var b05; +var b05; +var b05; +var b05; +var b05; diff --git a/tests/baselines/reference/mappedTypeModifiers.symbols b/tests/baselines/reference/mappedTypeModifiers.symbols index 6799d13d1acd5..8be2f53cec11e 100644 --- a/tests/baselines/reference/mappedTypeModifiers.symbols +++ b/tests/baselines/reference/mappedTypeModifiers.symbols @@ -5,25 +5,25 @@ type T = { a: number, b: string }; >a : Symbol(a, Decl(mappedTypeModifiers.ts, 1, 10)) >b : Symbol(b, Decl(mappedTypeModifiers.ts, 1, 21)) -type U = { a: number | undefined, b: string | undefined }; ->U : Symbol(U, Decl(mappedTypeModifiers.ts, 1, 34)) ->a : Symbol(a, Decl(mappedTypeModifiers.ts, 2, 10)) ->b : Symbol(b, Decl(mappedTypeModifiers.ts, 2, 33)) - -type P = { a?: number, b?: string }; ->P : Symbol(P, Decl(mappedTypeModifiers.ts, 2, 58)) ->a : Symbol(a, Decl(mappedTypeModifiers.ts, 3, 10)) ->b : Symbol(b, Decl(mappedTypeModifiers.ts, 3, 22)) - -type R = { readonly a: number, readonly b: string }; ->R : Symbol(R, Decl(mappedTypeModifiers.ts, 3, 36)) ->a : Symbol(a, Decl(mappedTypeModifiers.ts, 4, 10)) ->b : Symbol(b, Decl(mappedTypeModifiers.ts, 4, 30)) - -type PR = { readonly a?: number, readonly b?: string }; ->PR : Symbol(PR, Decl(mappedTypeModifiers.ts, 4, 52)) ->a : Symbol(a, Decl(mappedTypeModifiers.ts, 5, 11)) ->b : Symbol(b, Decl(mappedTypeModifiers.ts, 5, 32)) +type TU = { a: number | undefined, b: string | undefined }; +>TU : Symbol(TU, Decl(mappedTypeModifiers.ts, 1, 34)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 2, 11)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 2, 34)) + +type TP = { a?: number, b?: string }; +>TP : Symbol(TP, Decl(mappedTypeModifiers.ts, 2, 59)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 3, 11)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 3, 23)) + +type TR = { readonly a: number, readonly b: string }; +>TR : Symbol(TR, Decl(mappedTypeModifiers.ts, 3, 37)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 4, 11)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 4, 31)) + +type TPR = { readonly a?: number, readonly b?: string }; +>TPR : Symbol(TPR, Decl(mappedTypeModifiers.ts, 4, 53)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 5, 12)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 5, 33)) // Validate they all have the same keys var v00: "a" | "b"; @@ -33,31 +33,31 @@ var v00: keyof T; >v00 : Symbol(v00, Decl(mappedTypeModifiers.ts, 8, 3), Decl(mappedTypeModifiers.ts, 9, 3), Decl(mappedTypeModifiers.ts, 10, 3), Decl(mappedTypeModifiers.ts, 11, 3), Decl(mappedTypeModifiers.ts, 12, 3), Decl(mappedTypeModifiers.ts, 13, 3)) >T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) -var v00: keyof U; +var v00: keyof TU; >v00 : Symbol(v00, Decl(mappedTypeModifiers.ts, 8, 3), Decl(mappedTypeModifiers.ts, 9, 3), Decl(mappedTypeModifiers.ts, 10, 3), Decl(mappedTypeModifiers.ts, 11, 3), Decl(mappedTypeModifiers.ts, 12, 3), Decl(mappedTypeModifiers.ts, 13, 3)) ->U : Symbol(U, Decl(mappedTypeModifiers.ts, 1, 34)) +>TU : Symbol(TU, Decl(mappedTypeModifiers.ts, 1, 34)) -var v00: keyof P; +var v00: keyof TP; >v00 : Symbol(v00, Decl(mappedTypeModifiers.ts, 8, 3), Decl(mappedTypeModifiers.ts, 9, 3), Decl(mappedTypeModifiers.ts, 10, 3), Decl(mappedTypeModifiers.ts, 11, 3), Decl(mappedTypeModifiers.ts, 12, 3), Decl(mappedTypeModifiers.ts, 13, 3)) ->P : Symbol(P, Decl(mappedTypeModifiers.ts, 2, 58)) +>TP : Symbol(TP, Decl(mappedTypeModifiers.ts, 2, 59)) -var v00: keyof R; +var v00: keyof TR; >v00 : Symbol(v00, Decl(mappedTypeModifiers.ts, 8, 3), Decl(mappedTypeModifiers.ts, 9, 3), Decl(mappedTypeModifiers.ts, 10, 3), Decl(mappedTypeModifiers.ts, 11, 3), Decl(mappedTypeModifiers.ts, 12, 3), Decl(mappedTypeModifiers.ts, 13, 3)) ->R : Symbol(R, Decl(mappedTypeModifiers.ts, 3, 36)) +>TR : Symbol(TR, Decl(mappedTypeModifiers.ts, 3, 37)) -var v00: keyof PR; +var v00: keyof TPR; >v00 : Symbol(v00, Decl(mappedTypeModifiers.ts, 8, 3), Decl(mappedTypeModifiers.ts, 9, 3), Decl(mappedTypeModifiers.ts, 10, 3), Decl(mappedTypeModifiers.ts, 11, 3), Decl(mappedTypeModifiers.ts, 12, 3), Decl(mappedTypeModifiers.ts, 13, 3)) ->PR : Symbol(PR, Decl(mappedTypeModifiers.ts, 4, 52)) +>TPR : Symbol(TPR, Decl(mappedTypeModifiers.ts, 4, 53)) // Validate that non-isomorphic mapped types strip modifiers var v01: T; >v01 : Symbol(v01, Decl(mappedTypeModifiers.ts, 16, 3), Decl(mappedTypeModifiers.ts, 17, 3), Decl(mappedTypeModifiers.ts, 18, 3)) >T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) -var v01: Pick; +var v01: Pick; >v01 : Symbol(v01, Decl(mappedTypeModifiers.ts, 16, 3), Decl(mappedTypeModifiers.ts, 17, 3), Decl(mappedTypeModifiers.ts, 18, 3)) >Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) ->R : Symbol(R, Decl(mappedTypeModifiers.ts, 3, 36)) +>TR : Symbol(TR, Decl(mappedTypeModifiers.ts, 3, 37)) >T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) var v01: Pick, keyof T>; @@ -68,20 +68,20 @@ var v01: Pick, keyof T>; >T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) // Validate that non-isomorphic mapped types strip modifiers -var v02: U; +var v02: TU; >v02 : Symbol(v02, Decl(mappedTypeModifiers.ts, 21, 3), Decl(mappedTypeModifiers.ts, 22, 3), Decl(mappedTypeModifiers.ts, 23, 3), Decl(mappedTypeModifiers.ts, 24, 3), Decl(mappedTypeModifiers.ts, 25, 3)) ->U : Symbol(U, Decl(mappedTypeModifiers.ts, 1, 34)) +>TU : Symbol(TU, Decl(mappedTypeModifiers.ts, 1, 34)) -var v02: Pick; +var v02: Pick; >v02 : Symbol(v02, Decl(mappedTypeModifiers.ts, 21, 3), Decl(mappedTypeModifiers.ts, 22, 3), Decl(mappedTypeModifiers.ts, 23, 3), Decl(mappedTypeModifiers.ts, 24, 3), Decl(mappedTypeModifiers.ts, 25, 3)) >Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) ->P : Symbol(P, Decl(mappedTypeModifiers.ts, 2, 58)) +>TP : Symbol(TP, Decl(mappedTypeModifiers.ts, 2, 59)) >T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) -var v02: Pick; +var v02: Pick; >v02 : Symbol(v02, Decl(mappedTypeModifiers.ts, 21, 3), Decl(mappedTypeModifiers.ts, 22, 3), Decl(mappedTypeModifiers.ts, 23, 3), Decl(mappedTypeModifiers.ts, 24, 3), Decl(mappedTypeModifiers.ts, 25, 3)) >Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) ->PR : Symbol(PR, Decl(mappedTypeModifiers.ts, 4, 52)) +>TPR : Symbol(TPR, Decl(mappedTypeModifiers.ts, 4, 53)) >T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) var v02: Pick, keyof T>; @@ -100,9 +100,9 @@ var v02: Pick>, keyof T>; >T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) // Validate that isomorphic mapped types preserve optional modifier -var v03: P; +var v03: TP; >v03 : Symbol(v03, Decl(mappedTypeModifiers.ts, 28, 3), Decl(mappedTypeModifiers.ts, 29, 3)) ->P : Symbol(P, Decl(mappedTypeModifiers.ts, 2, 58)) +>TP : Symbol(TP, Decl(mappedTypeModifiers.ts, 2, 59)) var v03: Partial; >v03 : Symbol(v03, Decl(mappedTypeModifiers.ts, 28, 3), Decl(mappedTypeModifiers.ts, 29, 3)) @@ -110,9 +110,9 @@ var v03: Partial; >T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) // Validate that isomorphic mapped types preserve readonly modifier -var v04: R; +var v04: TR; >v04 : Symbol(v04, Decl(mappedTypeModifiers.ts, 32, 3), Decl(mappedTypeModifiers.ts, 33, 3)) ->R : Symbol(R, Decl(mappedTypeModifiers.ts, 3, 36)) +>TR : Symbol(TR, Decl(mappedTypeModifiers.ts, 3, 37)) var v04: Readonly; >v04 : Symbol(v04, Decl(mappedTypeModifiers.ts, 32, 3), Decl(mappedTypeModifiers.ts, 33, 3)) @@ -120,19 +120,19 @@ var v04: Readonly; >T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) // Validate that isomorphic mapped types preserve both partial and readonly modifiers -var v05: PR; +var v05: TPR; >v05 : Symbol(v05, Decl(mappedTypeModifiers.ts, 36, 3), Decl(mappedTypeModifiers.ts, 37, 3), Decl(mappedTypeModifiers.ts, 38, 3), Decl(mappedTypeModifiers.ts, 39, 3), Decl(mappedTypeModifiers.ts, 40, 3)) ->PR : Symbol(PR, Decl(mappedTypeModifiers.ts, 4, 52)) +>TPR : Symbol(TPR, Decl(mappedTypeModifiers.ts, 4, 53)) -var v05: Partial; +var v05: Partial; >v05 : Symbol(v05, Decl(mappedTypeModifiers.ts, 36, 3), Decl(mappedTypeModifiers.ts, 37, 3), Decl(mappedTypeModifiers.ts, 38, 3), Decl(mappedTypeModifiers.ts, 39, 3), Decl(mappedTypeModifiers.ts, 40, 3)) >Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) ->R : Symbol(R, Decl(mappedTypeModifiers.ts, 3, 36)) +>TR : Symbol(TR, Decl(mappedTypeModifiers.ts, 3, 37)) -var v05: Readonly

; +var v05: Readonly; >v05 : Symbol(v05, Decl(mappedTypeModifiers.ts, 36, 3), Decl(mappedTypeModifiers.ts, 37, 3), Decl(mappedTypeModifiers.ts, 38, 3), Decl(mappedTypeModifiers.ts, 39, 3), Decl(mappedTypeModifiers.ts, 40, 3)) >Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) ->P : Symbol(P, Decl(mappedTypeModifiers.ts, 2, 58)) +>TP : Symbol(TP, Decl(mappedTypeModifiers.ts, 2, 59)) var v05: Partial>; >v05 : Symbol(v05, Decl(mappedTypeModifiers.ts, 36, 3), Decl(mappedTypeModifiers.ts, 37, 3), Decl(mappedTypeModifiers.ts, 38, 3), Decl(mappedTypeModifiers.ts, 39, 3), Decl(mappedTypeModifiers.ts, 40, 3)) @@ -146,3 +146,168 @@ var v05: Readonly>; >Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) >T : Symbol(T, Decl(mappedTypeModifiers.ts, 0, 0)) +type Boxified = { [P in keyof T]: { x: T[P] } }; +>Boxified : Symbol(Boxified, Decl(mappedTypeModifiers.ts, 40, 30)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 42, 14)) +>P : Symbol(P, Decl(mappedTypeModifiers.ts, 42, 22)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 42, 14)) +>x : Symbol(x, Decl(mappedTypeModifiers.ts, 42, 38)) +>T : Symbol(T, Decl(mappedTypeModifiers.ts, 42, 14)) +>P : Symbol(P, Decl(mappedTypeModifiers.ts, 42, 22)) + +type B = { a: { x: number }, b: { x: string } }; +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 44, 10)) +>x : Symbol(x, Decl(mappedTypeModifiers.ts, 44, 15)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 44, 28)) +>x : Symbol(x, Decl(mappedTypeModifiers.ts, 44, 33)) + +type BU = { a: { x: number } | undefined, b: { x: string } | undefined }; +>BU : Symbol(BU, Decl(mappedTypeModifiers.ts, 44, 48)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 45, 11)) +>x : Symbol(x, Decl(mappedTypeModifiers.ts, 45, 16)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 45, 41)) +>x : Symbol(x, Decl(mappedTypeModifiers.ts, 45, 46)) + +type BP = { a?: { x: number }, b?: { x: string } }; +>BP : Symbol(BP, Decl(mappedTypeModifiers.ts, 45, 73)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 46, 11)) +>x : Symbol(x, Decl(mappedTypeModifiers.ts, 46, 17)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 46, 30)) +>x : Symbol(x, Decl(mappedTypeModifiers.ts, 46, 36)) + +type BR = { readonly a: { x: number }, readonly b: { x: string } }; +>BR : Symbol(BR, Decl(mappedTypeModifiers.ts, 46, 51)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 47, 11)) +>x : Symbol(x, Decl(mappedTypeModifiers.ts, 47, 25)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 47, 38)) +>x : Symbol(x, Decl(mappedTypeModifiers.ts, 47, 52)) + +type BPR = { readonly a?: { x: number }, readonly b?: { x: string } }; +>BPR : Symbol(BPR, Decl(mappedTypeModifiers.ts, 47, 67)) +>a : Symbol(a, Decl(mappedTypeModifiers.ts, 48, 12)) +>x : Symbol(x, Decl(mappedTypeModifiers.ts, 48, 27)) +>b : Symbol(b, Decl(mappedTypeModifiers.ts, 48, 40)) +>x : Symbol(x, Decl(mappedTypeModifiers.ts, 48, 55)) + +// Validate they all have the same keys +var b00: "a" | "b"; +>b00 : Symbol(b00, Decl(mappedTypeModifiers.ts, 51, 3), Decl(mappedTypeModifiers.ts, 52, 3), Decl(mappedTypeModifiers.ts, 53, 3), Decl(mappedTypeModifiers.ts, 54, 3), Decl(mappedTypeModifiers.ts, 55, 3), Decl(mappedTypeModifiers.ts, 56, 3)) + +var b00: keyof B; +>b00 : Symbol(b00, Decl(mappedTypeModifiers.ts, 51, 3), Decl(mappedTypeModifiers.ts, 52, 3), Decl(mappedTypeModifiers.ts, 53, 3), Decl(mappedTypeModifiers.ts, 54, 3), Decl(mappedTypeModifiers.ts, 55, 3), Decl(mappedTypeModifiers.ts, 56, 3)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + +var b00: keyof BU; +>b00 : Symbol(b00, Decl(mappedTypeModifiers.ts, 51, 3), Decl(mappedTypeModifiers.ts, 52, 3), Decl(mappedTypeModifiers.ts, 53, 3), Decl(mappedTypeModifiers.ts, 54, 3), Decl(mappedTypeModifiers.ts, 55, 3), Decl(mappedTypeModifiers.ts, 56, 3)) +>BU : Symbol(BU, Decl(mappedTypeModifiers.ts, 44, 48)) + +var b00: keyof BP; +>b00 : Symbol(b00, Decl(mappedTypeModifiers.ts, 51, 3), Decl(mappedTypeModifiers.ts, 52, 3), Decl(mappedTypeModifiers.ts, 53, 3), Decl(mappedTypeModifiers.ts, 54, 3), Decl(mappedTypeModifiers.ts, 55, 3), Decl(mappedTypeModifiers.ts, 56, 3)) +>BP : Symbol(BP, Decl(mappedTypeModifiers.ts, 45, 73)) + +var b00: keyof BR; +>b00 : Symbol(b00, Decl(mappedTypeModifiers.ts, 51, 3), Decl(mappedTypeModifiers.ts, 52, 3), Decl(mappedTypeModifiers.ts, 53, 3), Decl(mappedTypeModifiers.ts, 54, 3), Decl(mappedTypeModifiers.ts, 55, 3), Decl(mappedTypeModifiers.ts, 56, 3)) +>BR : Symbol(BR, Decl(mappedTypeModifiers.ts, 46, 51)) + +var b00: keyof BPR; +>b00 : Symbol(b00, Decl(mappedTypeModifiers.ts, 51, 3), Decl(mappedTypeModifiers.ts, 52, 3), Decl(mappedTypeModifiers.ts, 53, 3), Decl(mappedTypeModifiers.ts, 54, 3), Decl(mappedTypeModifiers.ts, 55, 3), Decl(mappedTypeModifiers.ts, 56, 3)) +>BPR : Symbol(BPR, Decl(mappedTypeModifiers.ts, 47, 67)) + +// Validate that non-isomorphic mapped types strip modifiers +var b01: B; +>b01 : Symbol(b01, Decl(mappedTypeModifiers.ts, 59, 3), Decl(mappedTypeModifiers.ts, 60, 3), Decl(mappedTypeModifiers.ts, 61, 3)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + +var b01: Pick; +>b01 : Symbol(b01, Decl(mappedTypeModifiers.ts, 59, 3), Decl(mappedTypeModifiers.ts, 60, 3), Decl(mappedTypeModifiers.ts, 61, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>BR : Symbol(BR, Decl(mappedTypeModifiers.ts, 46, 51)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + +var b01: Pick, keyof B>; +>b01 : Symbol(b01, Decl(mappedTypeModifiers.ts, 59, 3), Decl(mappedTypeModifiers.ts, 60, 3), Decl(mappedTypeModifiers.ts, 61, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>BR : Symbol(BR, Decl(mappedTypeModifiers.ts, 46, 51)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + +// Validate that non-isomorphic mapped types strip modifiers +var b02: BU; +>b02 : Symbol(b02, Decl(mappedTypeModifiers.ts, 64, 3), Decl(mappedTypeModifiers.ts, 65, 3), Decl(mappedTypeModifiers.ts, 66, 3), Decl(mappedTypeModifiers.ts, 67, 3), Decl(mappedTypeModifiers.ts, 68, 3)) +>BU : Symbol(BU, Decl(mappedTypeModifiers.ts, 44, 48)) + +var b02: Pick; +>b02 : Symbol(b02, Decl(mappedTypeModifiers.ts, 64, 3), Decl(mappedTypeModifiers.ts, 65, 3), Decl(mappedTypeModifiers.ts, 66, 3), Decl(mappedTypeModifiers.ts, 67, 3), Decl(mappedTypeModifiers.ts, 68, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>BP : Symbol(BP, Decl(mappedTypeModifiers.ts, 45, 73)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + +var b02: Pick; +>b02 : Symbol(b02, Decl(mappedTypeModifiers.ts, 64, 3), Decl(mappedTypeModifiers.ts, 65, 3), Decl(mappedTypeModifiers.ts, 66, 3), Decl(mappedTypeModifiers.ts, 67, 3), Decl(mappedTypeModifiers.ts, 68, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>BPR : Symbol(BPR, Decl(mappedTypeModifiers.ts, 47, 67)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + +var b02: Pick, keyof B>; +>b02 : Symbol(b02, Decl(mappedTypeModifiers.ts, 64, 3), Decl(mappedTypeModifiers.ts, 65, 3), Decl(mappedTypeModifiers.ts, 66, 3), Decl(mappedTypeModifiers.ts, 67, 3), Decl(mappedTypeModifiers.ts, 68, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + +var b02: Pick>, keyof B>; +>b02 : Symbol(b02, Decl(mappedTypeModifiers.ts, 64, 3), Decl(mappedTypeModifiers.ts, 65, 3), Decl(mappedTypeModifiers.ts, 66, 3), Decl(mappedTypeModifiers.ts, 67, 3), Decl(mappedTypeModifiers.ts, 68, 3)) +>Pick : Symbol(Pick, Decl(lib.d.ts, --, --)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + +// Validate that isomorphic mapped types preserve optional modifier +var b03: BP; +>b03 : Symbol(b03, Decl(mappedTypeModifiers.ts, 71, 3), Decl(mappedTypeModifiers.ts, 72, 3)) +>BP : Symbol(BP, Decl(mappedTypeModifiers.ts, 45, 73)) + +var b03: Partial; +>b03 : Symbol(b03, Decl(mappedTypeModifiers.ts, 71, 3), Decl(mappedTypeModifiers.ts, 72, 3)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + +// Validate that isomorphic mapped types preserve readonly modifier +var b04: BR; +>b04 : Symbol(b04, Decl(mappedTypeModifiers.ts, 75, 3), Decl(mappedTypeModifiers.ts, 76, 3)) +>BR : Symbol(BR, Decl(mappedTypeModifiers.ts, 46, 51)) + +var b04: Readonly; +>b04 : Symbol(b04, Decl(mappedTypeModifiers.ts, 75, 3), Decl(mappedTypeModifiers.ts, 76, 3)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + +// Validate that isomorphic mapped types preserve both partial and readonly modifiers +var b05: BPR; +>b05 : Symbol(b05, Decl(mappedTypeModifiers.ts, 79, 3), Decl(mappedTypeModifiers.ts, 80, 3), Decl(mappedTypeModifiers.ts, 81, 3), Decl(mappedTypeModifiers.ts, 82, 3), Decl(mappedTypeModifiers.ts, 83, 3)) +>BPR : Symbol(BPR, Decl(mappedTypeModifiers.ts, 47, 67)) + +var b05: Partial
; +>b05 : Symbol(b05, Decl(mappedTypeModifiers.ts, 79, 3), Decl(mappedTypeModifiers.ts, 80, 3), Decl(mappedTypeModifiers.ts, 81, 3), Decl(mappedTypeModifiers.ts, 82, 3), Decl(mappedTypeModifiers.ts, 83, 3)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>BR : Symbol(BR, Decl(mappedTypeModifiers.ts, 46, 51)) + +var b05: Readonly; +>b05 : Symbol(b05, Decl(mappedTypeModifiers.ts, 79, 3), Decl(mappedTypeModifiers.ts, 80, 3), Decl(mappedTypeModifiers.ts, 81, 3), Decl(mappedTypeModifiers.ts, 82, 3), Decl(mappedTypeModifiers.ts, 83, 3)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>BP : Symbol(BP, Decl(mappedTypeModifiers.ts, 45, 73)) + +var b05: Partial>; +>b05 : Symbol(b05, Decl(mappedTypeModifiers.ts, 79, 3), Decl(mappedTypeModifiers.ts, 80, 3), Decl(mappedTypeModifiers.ts, 81, 3), Decl(mappedTypeModifiers.ts, 82, 3), Decl(mappedTypeModifiers.ts, 83, 3)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + +var b05: Readonly>; +>b05 : Symbol(b05, Decl(mappedTypeModifiers.ts, 79, 3), Decl(mappedTypeModifiers.ts, 80, 3), Decl(mappedTypeModifiers.ts, 81, 3), Decl(mappedTypeModifiers.ts, 82, 3), Decl(mappedTypeModifiers.ts, 83, 3)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>B : Symbol(B, Decl(mappedTypeModifiers.ts, 42, 51)) + diff --git a/tests/baselines/reference/mappedTypeModifiers.types b/tests/baselines/reference/mappedTypeModifiers.types index 5c713991f7539..61b9bfc03b263 100644 --- a/tests/baselines/reference/mappedTypeModifiers.types +++ b/tests/baselines/reference/mappedTypeModifiers.types @@ -5,23 +5,23 @@ type T = { a: number, b: string }; >a : number >b : string -type U = { a: number | undefined, b: string | undefined }; ->U : U +type TU = { a: number | undefined, b: string | undefined }; +>TU : TU >a : number | undefined >b : string | undefined -type P = { a?: number, b?: string }; ->P : P +type TP = { a?: number, b?: string }; +>TP : TP >a : number | undefined >b : string | undefined -type R = { readonly a: number, readonly b: string }; ->R : R +type TR = { readonly a: number, readonly b: string }; +>TR : TR >a : number >b : string -type PR = { readonly a?: number, readonly b?: string }; ->PR : PR +type TPR = { readonly a?: number, readonly b?: string }; +>TPR : TPR >a : number | undefined >b : string | undefined @@ -33,31 +33,31 @@ var v00: keyof T; >v00 : "a" | "b" >T : T -var v00: keyof U; +var v00: keyof TU; >v00 : "a" | "b" ->U : U +>TU : TU -var v00: keyof P; +var v00: keyof TP; >v00 : "a" | "b" ->P : P +>TP : TP -var v00: keyof R; +var v00: keyof TR; >v00 : "a" | "b" ->R : R +>TR : TR -var v00: keyof PR; +var v00: keyof TPR; >v00 : "a" | "b" ->PR : PR +>TPR : TPR // Validate that non-isomorphic mapped types strip modifiers var v01: T; >v01 : T >T : T -var v01: Pick; +var v01: Pick; >v01 : T >Pick : Pick ->R : R +>TR : TR >T : T var v01: Pick, keyof T>; @@ -68,31 +68,31 @@ var v01: Pick, keyof T>; >T : T // Validate that non-isomorphic mapped types strip modifiers -var v02: U; ->v02 : U ->U : U +var v02: TU; +>v02 : TU +>TU : TU -var v02: Pick; ->v02 : U +var v02: Pick; +>v02 : TU >Pick : Pick ->P : P +>TP : TP >T : T -var v02: Pick; ->v02 : U +var v02: Pick; +>v02 : TU >Pick : Pick ->PR : PR +>TPR : TPR >T : T var v02: Pick, keyof T>; ->v02 : U +>v02 : TU >Pick : Pick >Partial : Partial >T : T >T : T var v02: Pick>, keyof T>; ->v02 : U +>v02 : TU >Pick : Pick >Partial : Partial >Readonly : Readonly @@ -100,49 +100,214 @@ var v02: Pick>, keyof T>; >T : T // Validate that isomorphic mapped types preserve optional modifier -var v03: P; ->v03 : P ->P : P +var v03: TP; +>v03 : TP +>TP : TP var v03: Partial; ->v03 : P +>v03 : TP >Partial : Partial >T : T // Validate that isomorphic mapped types preserve readonly modifier -var v04: R; ->v04 : R ->R : R +var v04: TR; +>v04 : TR +>TR : TR var v04: Readonly; ->v04 : R +>v04 : TR >Readonly : Readonly >T : T // Validate that isomorphic mapped types preserve both partial and readonly modifiers -var v05: PR; ->v05 : PR ->PR : PR +var v05: TPR; +>v05 : TPR +>TPR : TPR -var v05: Partial; ->v05 : PR +var v05: Partial; +>v05 : TPR >Partial : Partial ->R : R +>TR : TR -var v05: Readonly

; ->v05 : PR +var v05: Readonly; +>v05 : TPR >Readonly : Readonly ->P : P +>TP : TP var v05: Partial>; ->v05 : PR +>v05 : TPR >Partial : Partial >Readonly : Readonly >T : T var v05: Readonly>; ->v05 : PR +>v05 : TPR >Readonly : Readonly >Partial : Partial >T : T +type Boxified = { [P in keyof T]: { x: T[P] } }; +>Boxified : Boxified +>T : T +>P : P +>T : T +>x : T[P] +>T : T +>P : P + +type B = { a: { x: number }, b: { x: string } }; +>B : B +>a : { x: number; } +>x : number +>b : { x: string; } +>x : string + +type BU = { a: { x: number } | undefined, b: { x: string } | undefined }; +>BU : BU +>a : { x: number; } | undefined +>x : number +>b : { x: string; } | undefined +>x : string + +type BP = { a?: { x: number }, b?: { x: string } }; +>BP : BP +>a : { x: number; } | undefined +>x : number +>b : { x: string; } | undefined +>x : string + +type BR = { readonly a: { x: number }, readonly b: { x: string } }; +>BR : BR +>a : { x: number; } +>x : number +>b : { x: string; } +>x : string + +type BPR = { readonly a?: { x: number }, readonly b?: { x: string } }; +>BPR : BPR +>a : { x: number; } | undefined +>x : number +>b : { x: string; } | undefined +>x : string + +// Validate they all have the same keys +var b00: "a" | "b"; +>b00 : "a" | "b" + +var b00: keyof B; +>b00 : "a" | "b" +>B : B + +var b00: keyof BU; +>b00 : "a" | "b" +>BU : BU + +var b00: keyof BP; +>b00 : "a" | "b" +>BP : BP + +var b00: keyof BR; +>b00 : "a" | "b" +>BR : BR + +var b00: keyof BPR; +>b00 : "a" | "b" +>BPR : BPR + +// Validate that non-isomorphic mapped types strip modifiers +var b01: B; +>b01 : B +>B : B + +var b01: Pick; +>b01 : B +>Pick : Pick +>BR : BR +>B : B + +var b01: Pick, keyof B>; +>b01 : B +>Pick : Pick +>Readonly : Readonly +>BR : BR +>B : B + +// Validate that non-isomorphic mapped types strip modifiers +var b02: BU; +>b02 : BU +>BU : BU + +var b02: Pick; +>b02 : BU +>Pick : Pick +>BP : BP +>B : B + +var b02: Pick; +>b02 : BU +>Pick : Pick +>BPR : BPR +>B : B + +var b02: Pick, keyof B>; +>b02 : BU +>Pick : Pick +>Partial : Partial +>B : B +>B : B + +var b02: Pick>, keyof B>; +>b02 : BU +>Pick : Pick +>Partial : Partial +>Readonly : Readonly +>B : B +>B : B + +// Validate that isomorphic mapped types preserve optional modifier +var b03: BP; +>b03 : BP +>BP : BP + +var b03: Partial; +>b03 : BP +>Partial : Partial +>B : B + +// Validate that isomorphic mapped types preserve readonly modifier +var b04: BR; +>b04 : BR +>BR : BR + +var b04: Readonly; +>b04 : BR +>Readonly : Readonly +>B : B + +// Validate that isomorphic mapped types preserve both partial and readonly modifiers +var b05: BPR; +>b05 : BPR +>BPR : BPR + +var b05: Partial
; +>b05 : BPR +>Partial : Partial +>BR : BR + +var b05: Readonly; +>b05 : BPR +>Readonly : Readonly +>BP : BP + +var b05: Partial>; +>b05 : BPR +>Partial : Partial +>Readonly : Readonly +>B : B + +var b05: Readonly>; +>b05 : BPR +>Readonly : Readonly +>Partial : Partial +>B : B + diff --git a/tests/cases/conformance/types/mapped/mappedTypeModifiers.ts b/tests/cases/conformance/types/mapped/mappedTypeModifiers.ts index 947f0c579a1c8..1e76c5b745284 100644 --- a/tests/cases/conformance/types/mapped/mappedTypeModifiers.ts +++ b/tests/cases/conformance/types/mapped/mappedTypeModifiers.ts @@ -1,42 +1,85 @@ // @strictNullChecks: true type T = { a: number, b: string }; -type U = { a: number | undefined, b: string | undefined }; -type P = { a?: number, b?: string }; -type R = { readonly a: number, readonly b: string }; -type PR = { readonly a?: number, readonly b?: string }; +type TU = { a: number | undefined, b: string | undefined }; +type TP = { a?: number, b?: string }; +type TR = { readonly a: number, readonly b: string }; +type TPR = { readonly a?: number, readonly b?: string }; // Validate they all have the same keys var v00: "a" | "b"; var v00: keyof T; -var v00: keyof U; -var v00: keyof P; -var v00: keyof R; -var v00: keyof PR; +var v00: keyof TU; +var v00: keyof TP; +var v00: keyof TR; +var v00: keyof TPR; // Validate that non-isomorphic mapped types strip modifiers var v01: T; -var v01: Pick; +var v01: Pick; var v01: Pick, keyof T>; // Validate that non-isomorphic mapped types strip modifiers -var v02: U; -var v02: Pick; -var v02: Pick; +var v02: TU; +var v02: Pick; +var v02: Pick; var v02: Pick, keyof T>; var v02: Pick>, keyof T>; // Validate that isomorphic mapped types preserve optional modifier -var v03: P; +var v03: TP; var v03: Partial; // Validate that isomorphic mapped types preserve readonly modifier -var v04: R; +var v04: TR; var v04: Readonly; // Validate that isomorphic mapped types preserve both partial and readonly modifiers -var v05: PR; -var v05: Partial; -var v05: Readonly

; +var v05: TPR; +var v05: Partial; +var v05: Readonly; var v05: Partial>; -var v05: Readonly>; \ No newline at end of file +var v05: Readonly>; + +type Boxified = { [P in keyof T]: { x: T[P] } }; + +type B = { a: { x: number }, b: { x: string } }; +type BU = { a: { x: number } | undefined, b: { x: string } | undefined }; +type BP = { a?: { x: number }, b?: { x: string } }; +type BR = { readonly a: { x: number }, readonly b: { x: string } }; +type BPR = { readonly a?: { x: number }, readonly b?: { x: string } }; + +// Validate they all have the same keys +var b00: "a" | "b"; +var b00: keyof B; +var b00: keyof BU; +var b00: keyof BP; +var b00: keyof BR; +var b00: keyof BPR; + +// Validate that non-isomorphic mapped types strip modifiers +var b01: B; +var b01: Pick; +var b01: Pick, keyof B>; + +// Validate that non-isomorphic mapped types strip modifiers +var b02: BU; +var b02: Pick; +var b02: Pick; +var b02: Pick, keyof B>; +var b02: Pick>, keyof B>; + +// Validate that isomorphic mapped types preserve optional modifier +var b03: BP; +var b03: Partial; + +// Validate that isomorphic mapped types preserve readonly modifier +var b04: BR; +var b04: Readonly; + +// Validate that isomorphic mapped types preserve both partial and readonly modifiers +var b05: BPR; +var b05: Partial
; +var b05: Readonly; +var b05: Partial>; +var b05: Readonly>; \ No newline at end of file