From 8eb24db0c0a0dae47e2696095d46f894546105aa Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 29 Jul 2018 15:14:01 -0700 Subject: [PATCH 1/4] Homomorphic mapped type support for arrays and tuples --- src/compiler/checker.ts | 65 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2b255da7ae34d..a708e5e86b64c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8432,6 +8432,10 @@ namespace ts { return createTypeFromGenericGlobalType(globalArrayType, [elementType]); } + function createReadonlyArrayType(elementType: Type): ObjectType { + return createTypeFromGenericGlobalType(globalReadonlyArrayType, [elementType]); + } + function getTypeFromArrayTypeNode(node: ArrayTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { @@ -10087,11 +10091,16 @@ namespace ts { } function instantiateMappedType(type: MappedType, mapper: TypeMapper): Type { - // Check if we have a homomorphic mapped type, i.e. a type of the form { [P in keyof T]: X } for some - // type variable T. If so, the mapped type is distributive over a union type and when T is instantiated - // to a union type A | B, we produce { [P in keyof A]: X } | { [P in keyof B]: X }. Furthermore, for - // homomorphic mapped types we leave primitive types alone. For example, when T is instantiated to a - // union type A | undefined, we produce { [P in keyof A]: X } | undefined. + // For a momomorphic mapped type { [P in keyof T]: X }, where T is some type variable, the mapping + // operation depends on T as follows: + // * If T is a primitive type no mapping is performed and the result is simply T. + // * If T is a union type we distribute the mapped type over the union. + // * If T is an array we map to an array where the element type has been transformed. + // * If T is a tuple we map to a tuple where the element types have been transformed. + // * Otherwise we map to an object type where the type of each property has been transformed. + // For example, when T is instantiated to a union type A | B, we produce { [P in keyof A]: X } | + // { [P in keyof B]: X }, and when when T is instantiated to a union type A | undefined, we produce + // { [P in keyof A]: X } | undefined. const constraintType = getConstraintTypeFromMappedType(type); if (constraintType.flags & TypeFlags.Index) { const typeVariable = (constraintType).type; @@ -10100,7 +10109,11 @@ namespace ts { if (typeVariable !== mappedTypeVariable) { return mapType(mappedTypeVariable, t => { if (isMappableType(t)) { - return instantiateAnonymousType(type, createReplacementMapper(typeVariable, t, mapper)); + const replacementMapper = createReplacementMapper(typeVariable, t, mapper); + return isArrayType(t) ? createArrayType(instantiateMappedTypeTemplate(type, numberType, /*isOptional*/ true, replacementMapper)) : + isReadonlyArrayType(t) ? createReadonlyArrayType(instantiateMappedTypeTemplate(type, numberType, /*isOptional*/ true, replacementMapper)) : + isTupleType(t) ? instantiateMappedTupleType(t, type, replacementMapper) : + instantiateAnonymousType(type, replacementMapper); } return t; }); @@ -10114,6 +10127,26 @@ namespace ts { return type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection); } + function instantiateMappedTupleType(tupleType: TupleTypeReference, mappedType: MappedType, mapper: TypeMapper) { + const minLength = tupleType.target.minLength; + const elementTypes = map(tupleType.typeArguments || emptyArray, (_, i) => + instantiateMappedTypeTemplate(mappedType, getLiteralType("" + i), i >= minLength, mapper)); + const modifiers = getMappedTypeModifiers(mappedType); + const newMinLength = modifiers & MappedTypeModifiers.IncludeOptional ? 0 : + modifiers & MappedTypeModifiers.ExcludeOptional ? getTypeReferenceArity(tupleType) - (tupleType.target.hasRestElement ? 1 : 0) : + minLength; + return createTupleType(elementTypes, newMinLength, tupleType.target.hasRestElement, tupleType.target.associatedNames); + } + + function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) { + const templateMapper = combineTypeMappers(mapper, createTypeMapper([getTypeParameterFromMappedType(type)], [key])); + const propType = instantiateType(getTemplateTypeFromMappedType(type.target || type), templateMapper); + const modifiers = getMappedTypeModifiers(type); + return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !isTypeAssignableTo(undefinedType, propType) ? getOptionalType(propType) : + strictNullChecks && modifiers & MappedTypeModifiers.ExcludeOptional && isOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) : + propType; + } + function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper): AnonymousType { const result = createObjectType(type.objectFlags | ObjectFlags.Instantiated, type.symbol); if (type.objectFlags & ObjectFlags.Mapped) { @@ -12441,6 +12474,10 @@ namespace ts { return !!(getObjectFlags(type) & ObjectFlags.Reference) && (type).target === globalArrayType; } + function isReadonlyArrayType(type: Type): boolean { + return !!(getObjectFlags(type) & ObjectFlags.Reference) && (type).target === globalReadonlyArrayType; + } + function isArrayLikeType(type: Type): boolean { // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, // or if it is not the undefined or null type and if it is assignable to ReadonlyArray @@ -12996,6 +13033,22 @@ namespace ts { return undefined; } } + // For arrays and tuples we infer new arrays and tuples where the reverse mapping has been + // applied to the element type(s). + if (isArrayType(source)) { + return createArrayType(inferReverseMappedType((source).typeArguments![0], target)); + } + if (isReadonlyArrayType(source)) { + return createReadonlyArrayType(inferReverseMappedType((source).typeArguments![0], target)); + } + if (isTupleType(source)) { + const elementTypes = map(source.typeArguments || emptyArray, t => inferReverseMappedType(t, target)); + const minLength = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ? + getTypeReferenceArity(source) - (source.target.hasRestElement ? 1 : 0) : source.target.minLength; + return createTupleType(elementTypes, minLength, source.target.hasRestElement, source.target.associatedNames); + } + // For all other object types we infer a new object type where the reverse mapping has been + // applied to the type of each property. const reversed = createObjectType(ObjectFlags.ReverseMapped | ObjectFlags.Anonymous, /*symbol*/ undefined) as ReverseMappedType; reversed.source = source; reversed.mappedType = target; From df100957b62d918ea176c421bf2178b9ea892fcd Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 29 Jul 2018 15:14:44 -0700 Subject: [PATCH 2/4] Accept new baselines --- tests/baselines/reference/mappedTypes4.types | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/baselines/reference/mappedTypes4.types b/tests/baselines/reference/mappedTypes4.types index 7292e143b42b0..d90b0cf605e0d 100644 --- a/tests/baselines/reference/mappedTypes4.types +++ b/tests/baselines/reference/mappedTypes4.types @@ -103,7 +103,7 @@ type T01 = Readonly; >null : null type T02 = Boxified ->T02 : string | Boxified | Boxified | Boxified +>T02 : string | Boxified | Boxified | Box[] >Boxified : Boxified >A : A >B : B From 32a9ec6c30652de28e1f38fb51580193ccb44c59 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 29 Jul 2018 15:25:54 -0700 Subject: [PATCH 3/4] Add tests --- .../types/mapped/mappedTypesArraysTuples.ts | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tests/cases/conformance/types/mapped/mappedTypesArraysTuples.ts diff --git a/tests/cases/conformance/types/mapped/mappedTypesArraysTuples.ts b/tests/cases/conformance/types/mapped/mappedTypesArraysTuples.ts new file mode 100644 index 0000000000000..0607462fe049c --- /dev/null +++ b/tests/cases/conformance/types/mapped/mappedTypesArraysTuples.ts @@ -0,0 +1,65 @@ +// @strict: true +// @declaration: true + +type Box = { value: T }; +type Boxified = { [P in keyof T]: Box }; + +type T00 = Boxified<[number, string?, ...boolean[]]>; +type T01 = Partial<[number, string?, ...boolean[]]>; +type T02 = Required<[number, string?, ...boolean[]]>; + +type T10 = Boxified; +type T11 = Partial; +type T12 = Required; +type T13 = Boxified>; +type T14 = Partial>; +type T15 = Required>; + +type T20 = Boxified<(string | undefined)[]>; +type T21 = Partial<(string | undefined)[]>; +type T22 = Required<(string | undefined)[]>; +type T23 = Boxified>; +type T24 = Partial>; +type T25 = Required>; + +type T30 = Boxified>; +type T31 = Partial>; + +type A = { a: string }; +type B = { b: string }; + +type T40 = Boxified | [A, B] | string | string[]>; + +declare function unboxify(x: Boxified): T; + +declare let x10: [Box, Box, ...Box[]]; +let y10 = unboxify(x10); + +declare let x11: Box[]; +let y11 = unboxify(x11); + +declare let x12: { a: Box, b: Box }; +let y12 = unboxify(x12); + +declare function nonpartial(x: Partial): T; + +declare let x20: [number | undefined, string?, ...boolean[]]; +let y20 = nonpartial(x20); + +declare let x21: (number | undefined)[]; +let y21 = nonpartial(x21); + +declare let x22: { a: number | undefined, b?: string[] }; +let y22 = nonpartial(x22); + +type Awaited = T extends PromiseLike ? U : T; +type Awaitified = { [P in keyof T]: Awaited }; + +declare function all(...values: T): Promise>; + +function f1(a: number, b: Promise, c: string[], d: Promise) { + let x1 = all(a); + let x2 = all(a, b); + let x3 = all(a, b, c); + let x4 = all(a, b, c, d); +} From efb6e0b84222fffe3ffc4fa774e701c32aed2eea Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 29 Jul 2018 15:26:03 -0700 Subject: [PATCH 4/4] Accept new baselines --- .../reference/mappedTypesArraysTuples.js | 144 ++++++++++ .../reference/mappedTypesArraysTuples.symbols | 247 +++++++++++++++++ .../reference/mappedTypesArraysTuples.types | 257 ++++++++++++++++++ 3 files changed, 648 insertions(+) create mode 100644 tests/baselines/reference/mappedTypesArraysTuples.js create mode 100644 tests/baselines/reference/mappedTypesArraysTuples.symbols create mode 100644 tests/baselines/reference/mappedTypesArraysTuples.types diff --git a/tests/baselines/reference/mappedTypesArraysTuples.js b/tests/baselines/reference/mappedTypesArraysTuples.js new file mode 100644 index 0000000000000..489d8493e0868 --- /dev/null +++ b/tests/baselines/reference/mappedTypesArraysTuples.js @@ -0,0 +1,144 @@ +//// [mappedTypesArraysTuples.ts] +type Box = { value: T }; +type Boxified = { [P in keyof T]: Box }; + +type T00 = Boxified<[number, string?, ...boolean[]]>; +type T01 = Partial<[number, string?, ...boolean[]]>; +type T02 = Required<[number, string?, ...boolean[]]>; + +type T10 = Boxified; +type T11 = Partial; +type T12 = Required; +type T13 = Boxified>; +type T14 = Partial>; +type T15 = Required>; + +type T20 = Boxified<(string | undefined)[]>; +type T21 = Partial<(string | undefined)[]>; +type T22 = Required<(string | undefined)[]>; +type T23 = Boxified>; +type T24 = Partial>; +type T25 = Required>; + +type T30 = Boxified>; +type T31 = Partial>; + +type A = { a: string }; +type B = { b: string }; + +type T40 = Boxified | [A, B] | string | string[]>; + +declare function unboxify(x: Boxified): T; + +declare let x10: [Box, Box, ...Box[]]; +let y10 = unboxify(x10); + +declare let x11: Box[]; +let y11 = unboxify(x11); + +declare let x12: { a: Box, b: Box }; +let y12 = unboxify(x12); + +declare function nonpartial(x: Partial): T; + +declare let x20: [number | undefined, string?, ...boolean[]]; +let y20 = nonpartial(x20); + +declare let x21: (number | undefined)[]; +let y21 = nonpartial(x21); + +declare let x22: { a: number | undefined, b?: string[] }; +let y22 = nonpartial(x22); + +type Awaited = T extends PromiseLike ? U : T; +type Awaitified = { [P in keyof T]: Awaited }; + +declare function all(...values: T): Promise>; + +function f1(a: number, b: Promise, c: string[], d: Promise) { + let x1 = all(a); + let x2 = all(a, b); + let x3 = all(a, b, c); + let x4 = all(a, b, c, d); +} + + +//// [mappedTypesArraysTuples.js] +"use strict"; +var y10 = unboxify(x10); +var y11 = unboxify(x11); +var y12 = unboxify(x12); +var y20 = nonpartial(x20); +var y21 = nonpartial(x21); +var y22 = nonpartial(x22); +function f1(a, b, c, d) { + var x1 = all(a); + var x2 = all(a, b); + var x3 = all(a, b, c); + var x4 = all(a, b, c, d); +} + + +//// [mappedTypesArraysTuples.d.ts] +declare type Box = { + value: T; +}; +declare type Boxified = { + [P in keyof T]: Box; +}; +declare type T00 = Boxified<[number, string?, ...boolean[]]>; +declare type T01 = Partial<[number, string?, ...boolean[]]>; +declare type T02 = Required<[number, string?, ...boolean[]]>; +declare type T10 = Boxified; +declare type T11 = Partial; +declare type T12 = Required; +declare type T13 = Boxified>; +declare type T14 = Partial>; +declare type T15 = Required>; +declare type T20 = Boxified<(string | undefined)[]>; +declare type T21 = Partial<(string | undefined)[]>; +declare type T22 = Required<(string | undefined)[]>; +declare type T23 = Boxified>; +declare type T24 = Partial>; +declare type T25 = Required>; +declare type T30 = Boxified>; +declare type T31 = Partial>; +declare type A = { + a: string; +}; +declare type B = { + b: string; +}; +declare type T40 = Boxified | [A, B] | string | string[]>; +declare function unboxify(x: Boxified): T; +declare let x10: [Box, Box, ...Box[]]; +declare let y10: [number, string, ...boolean[]]; +declare let x11: Box[]; +declare let y11: number[]; +declare let x12: { + a: Box; + b: Box; +}; +declare let y12: { + a: number; + b: string[]; +}; +declare function nonpartial(x: Partial): T; +declare let x20: [number | undefined, string?, ...boolean[]]; +declare let y20: [number, string, ...boolean[]]; +declare let x21: (number | undefined)[]; +declare let y21: number[]; +declare let x22: { + a: number | undefined; + b?: string[]; +}; +declare let y22: { + a: number; + b: string[]; +}; +declare type Awaited = T extends PromiseLike ? U : T; +declare type Awaitified = { + [P in keyof T]: Awaited; +}; +declare function all(...values: T): Promise>; +declare function f1(a: number, b: Promise, c: string[], d: Promise): void; diff --git a/tests/baselines/reference/mappedTypesArraysTuples.symbols b/tests/baselines/reference/mappedTypesArraysTuples.symbols new file mode 100644 index 0000000000000..7d743235a42b5 --- /dev/null +++ b/tests/baselines/reference/mappedTypesArraysTuples.symbols @@ -0,0 +1,247 @@ +=== tests/cases/conformance/types/mapped/mappedTypesArraysTuples.ts === +type Box = { value: T }; +>Box : Symbol(Box, Decl(mappedTypesArraysTuples.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 0, 9)) +>value : Symbol(value, Decl(mappedTypesArraysTuples.ts, 0, 15)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 0, 9)) + +type Boxified = { [P in keyof T]: Box }; +>Boxified : Symbol(Boxified, Decl(mappedTypesArraysTuples.ts, 0, 27)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 1, 14)) +>P : Symbol(P, Decl(mappedTypesArraysTuples.ts, 1, 22)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 1, 14)) +>Box : Symbol(Box, Decl(mappedTypesArraysTuples.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 1, 14)) +>P : Symbol(P, Decl(mappedTypesArraysTuples.ts, 1, 22)) + +type T00 = Boxified<[number, string?, ...boolean[]]>; +>T00 : Symbol(T00, Decl(mappedTypesArraysTuples.ts, 1, 49)) +>Boxified : Symbol(Boxified, Decl(mappedTypesArraysTuples.ts, 0, 27)) + +type T01 = Partial<[number, string?, ...boolean[]]>; +>T01 : Symbol(T01, Decl(mappedTypesArraysTuples.ts, 3, 53)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) + +type T02 = Required<[number, string?, ...boolean[]]>; +>T02 : Symbol(T02, Decl(mappedTypesArraysTuples.ts, 4, 52)) +>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --)) + +type T10 = Boxified; +>T10 : Symbol(T10, Decl(mappedTypesArraysTuples.ts, 5, 53)) +>Boxified : Symbol(Boxified, Decl(mappedTypesArraysTuples.ts, 0, 27)) + +type T11 = Partial; +>T11 : Symbol(T11, Decl(mappedTypesArraysTuples.ts, 7, 30)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) + +type T12 = Required; +>T12 : Symbol(T12, Decl(mappedTypesArraysTuples.ts, 8, 29)) +>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --)) + +type T13 = Boxified>; +>T13 : Symbol(T13, Decl(mappedTypesArraysTuples.ts, 9, 30)) +>Boxified : Symbol(Boxified, Decl(mappedTypesArraysTuples.ts, 0, 27)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) + +type T14 = Partial>; +>T14 : Symbol(T14, Decl(mappedTypesArraysTuples.ts, 10, 43)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) + +type T15 = Required>; +>T15 : Symbol(T15, Decl(mappedTypesArraysTuples.ts, 11, 42)) +>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) + +type T20 = Boxified<(string | undefined)[]>; +>T20 : Symbol(T20, Decl(mappedTypesArraysTuples.ts, 12, 43)) +>Boxified : Symbol(Boxified, Decl(mappedTypesArraysTuples.ts, 0, 27)) + +type T21 = Partial<(string | undefined)[]>; +>T21 : Symbol(T21, Decl(mappedTypesArraysTuples.ts, 14, 44)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) + +type T22 = Required<(string | undefined)[]>; +>T22 : Symbol(T22, Decl(mappedTypesArraysTuples.ts, 15, 43)) +>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --)) + +type T23 = Boxified>; +>T23 : Symbol(T23, Decl(mappedTypesArraysTuples.ts, 16, 44)) +>Boxified : Symbol(Boxified, Decl(mappedTypesArraysTuples.ts, 0, 27)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) + +type T24 = Partial>; +>T24 : Symbol(T24, Decl(mappedTypesArraysTuples.ts, 17, 55)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) + +type T25 = Required>; +>T25 : Symbol(T25, Decl(mappedTypesArraysTuples.ts, 18, 54)) +>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) + +type T30 = Boxified>; +>T30 : Symbol(T30, Decl(mappedTypesArraysTuples.ts, 19, 55)) +>Boxified : Symbol(Boxified, Decl(mappedTypesArraysTuples.ts, 0, 27)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) + +type T31 = Partial>; +>T31 : Symbol(T31, Decl(mappedTypesArraysTuples.ts, 21, 39)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>Boxified : Symbol(Boxified, Decl(mappedTypesArraysTuples.ts, 0, 27)) + +type A = { a: string }; +>A : Symbol(A, Decl(mappedTypesArraysTuples.ts, 22, 39)) +>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 24, 10)) + +type B = { b: string }; +>B : Symbol(B, Decl(mappedTypesArraysTuples.ts, 24, 23)) +>b : Symbol(b, Decl(mappedTypesArraysTuples.ts, 25, 10)) + +type T40 = Boxified | [A, B] | string | string[]>; +>T40 : Symbol(T40, Decl(mappedTypesArraysTuples.ts, 25, 23)) +>Boxified : Symbol(Boxified, Decl(mappedTypesArraysTuples.ts, 0, 27)) +>A : Symbol(A, Decl(mappedTypesArraysTuples.ts, 22, 39)) +>A : Symbol(A, Decl(mappedTypesArraysTuples.ts, 22, 39)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(mappedTypesArraysTuples.ts, 22, 39)) +>A : Symbol(A, Decl(mappedTypesArraysTuples.ts, 22, 39)) +>B : Symbol(B, Decl(mappedTypesArraysTuples.ts, 24, 23)) + +declare function unboxify(x: Boxified): T; +>unboxify : Symbol(unboxify, Decl(mappedTypesArraysTuples.ts, 27, 77)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 29, 26)) +>x : Symbol(x, Decl(mappedTypesArraysTuples.ts, 29, 29)) +>Boxified : Symbol(Boxified, Decl(mappedTypesArraysTuples.ts, 0, 27)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 29, 26)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 29, 26)) + +declare let x10: [Box, Box, ...Box[]]; +>x10 : Symbol(x10, Decl(mappedTypesArraysTuples.ts, 31, 11)) +>Box : Symbol(Box, Decl(mappedTypesArraysTuples.ts, 0, 0)) +>Box : Symbol(Box, Decl(mappedTypesArraysTuples.ts, 0, 0)) +>Box : Symbol(Box, Decl(mappedTypesArraysTuples.ts, 0, 0)) + +let y10 = unboxify(x10); +>y10 : Symbol(y10, Decl(mappedTypesArraysTuples.ts, 32, 3)) +>unboxify : Symbol(unboxify, Decl(mappedTypesArraysTuples.ts, 27, 77)) +>x10 : Symbol(x10, Decl(mappedTypesArraysTuples.ts, 31, 11)) + +declare let x11: Box[]; +>x11 : Symbol(x11, Decl(mappedTypesArraysTuples.ts, 34, 11)) +>Box : Symbol(Box, Decl(mappedTypesArraysTuples.ts, 0, 0)) + +let y11 = unboxify(x11); +>y11 : Symbol(y11, Decl(mappedTypesArraysTuples.ts, 35, 3)) +>unboxify : Symbol(unboxify, Decl(mappedTypesArraysTuples.ts, 27, 77)) +>x11 : Symbol(x11, Decl(mappedTypesArraysTuples.ts, 34, 11)) + +declare let x12: { a: Box, b: Box }; +>x12 : Symbol(x12, Decl(mappedTypesArraysTuples.ts, 37, 11)) +>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 37, 18)) +>Box : Symbol(Box, Decl(mappedTypesArraysTuples.ts, 0, 0)) +>b : Symbol(b, Decl(mappedTypesArraysTuples.ts, 37, 34)) +>Box : Symbol(Box, Decl(mappedTypesArraysTuples.ts, 0, 0)) + +let y12 = unboxify(x12); +>y12 : Symbol(y12, Decl(mappedTypesArraysTuples.ts, 38, 3)) +>unboxify : Symbol(unboxify, Decl(mappedTypesArraysTuples.ts, 27, 77)) +>x12 : Symbol(x12, Decl(mappedTypesArraysTuples.ts, 37, 11)) + +declare function nonpartial(x: Partial): T; +>nonpartial : Symbol(nonpartial, Decl(mappedTypesArraysTuples.ts, 38, 24)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 40, 28)) +>x : Symbol(x, Decl(mappedTypesArraysTuples.ts, 40, 31)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 40, 28)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 40, 28)) + +declare let x20: [number | undefined, string?, ...boolean[]]; +>x20 : Symbol(x20, Decl(mappedTypesArraysTuples.ts, 42, 11)) + +let y20 = nonpartial(x20); +>y20 : Symbol(y20, Decl(mappedTypesArraysTuples.ts, 43, 3)) +>nonpartial : Symbol(nonpartial, Decl(mappedTypesArraysTuples.ts, 38, 24)) +>x20 : Symbol(x20, Decl(mappedTypesArraysTuples.ts, 42, 11)) + +declare let x21: (number | undefined)[]; +>x21 : Symbol(x21, Decl(mappedTypesArraysTuples.ts, 45, 11)) + +let y21 = nonpartial(x21); +>y21 : Symbol(y21, Decl(mappedTypesArraysTuples.ts, 46, 3)) +>nonpartial : Symbol(nonpartial, Decl(mappedTypesArraysTuples.ts, 38, 24)) +>x21 : Symbol(x21, Decl(mappedTypesArraysTuples.ts, 45, 11)) + +declare let x22: { a: number | undefined, b?: string[] }; +>x22 : Symbol(x22, Decl(mappedTypesArraysTuples.ts, 48, 11)) +>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 48, 18)) +>b : Symbol(b, Decl(mappedTypesArraysTuples.ts, 48, 41)) + +let y22 = nonpartial(x22); +>y22 : Symbol(y22, Decl(mappedTypesArraysTuples.ts, 49, 3)) +>nonpartial : Symbol(nonpartial, Decl(mappedTypesArraysTuples.ts, 38, 24)) +>x22 : Symbol(x22, Decl(mappedTypesArraysTuples.ts, 48, 11)) + +type Awaited = T extends PromiseLike ? U : T; +>Awaited : Symbol(Awaited, Decl(mappedTypesArraysTuples.ts, 49, 26)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 51, 13)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 51, 13)) +>PromiseLike : Symbol(PromiseLike, Decl(lib.es5.d.ts, --, --)) +>U : Symbol(U, Decl(mappedTypesArraysTuples.ts, 51, 45)) +>U : Symbol(U, Decl(mappedTypesArraysTuples.ts, 51, 45)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 51, 13)) + +type Awaitified = { [P in keyof T]: Awaited }; +>Awaitified : Symbol(Awaitified, Decl(mappedTypesArraysTuples.ts, 51, 57)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 52, 16)) +>P : Symbol(P, Decl(mappedTypesArraysTuples.ts, 52, 24)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 52, 16)) +>Awaited : Symbol(Awaited, Decl(mappedTypesArraysTuples.ts, 49, 26)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 52, 16)) +>P : Symbol(P, Decl(mappedTypesArraysTuples.ts, 52, 24)) + +declare function all(...values: T): Promise>; +>all : Symbol(all, Decl(mappedTypesArraysTuples.ts, 52, 55)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 54, 21)) +>values : Symbol(values, Decl(mappedTypesArraysTuples.ts, 54, 38)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 54, 21)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) +>Awaitified : Symbol(Awaitified, Decl(mappedTypesArraysTuples.ts, 51, 57)) +>T : Symbol(T, Decl(mappedTypesArraysTuples.ts, 54, 21)) + +function f1(a: number, b: Promise, c: string[], d: Promise) { +>f1 : Symbol(f1, Decl(mappedTypesArraysTuples.ts, 54, 76)) +>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 56, 12)) +>b : Symbol(b, Decl(mappedTypesArraysTuples.ts, 56, 22)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) +>c : Symbol(c, Decl(mappedTypesArraysTuples.ts, 56, 42)) +>d : Symbol(d, Decl(mappedTypesArraysTuples.ts, 56, 55)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + let x1 = all(a); +>x1 : Symbol(x1, Decl(mappedTypesArraysTuples.ts, 57, 7)) +>all : Symbol(all, Decl(mappedTypesArraysTuples.ts, 52, 55)) +>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 56, 12)) + + let x2 = all(a, b); +>x2 : Symbol(x2, Decl(mappedTypesArraysTuples.ts, 58, 7)) +>all : Symbol(all, Decl(mappedTypesArraysTuples.ts, 52, 55)) +>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 56, 12)) +>b : Symbol(b, Decl(mappedTypesArraysTuples.ts, 56, 22)) + + let x3 = all(a, b, c); +>x3 : Symbol(x3, Decl(mappedTypesArraysTuples.ts, 59, 7)) +>all : Symbol(all, Decl(mappedTypesArraysTuples.ts, 52, 55)) +>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 56, 12)) +>b : Symbol(b, Decl(mappedTypesArraysTuples.ts, 56, 22)) +>c : Symbol(c, Decl(mappedTypesArraysTuples.ts, 56, 42)) + + let x4 = all(a, b, c, d); +>x4 : Symbol(x4, Decl(mappedTypesArraysTuples.ts, 60, 7)) +>all : Symbol(all, Decl(mappedTypesArraysTuples.ts, 52, 55)) +>a : Symbol(a, Decl(mappedTypesArraysTuples.ts, 56, 12)) +>b : Symbol(b, Decl(mappedTypesArraysTuples.ts, 56, 22)) +>c : Symbol(c, Decl(mappedTypesArraysTuples.ts, 56, 42)) +>d : Symbol(d, Decl(mappedTypesArraysTuples.ts, 56, 55)) +} + diff --git a/tests/baselines/reference/mappedTypesArraysTuples.types b/tests/baselines/reference/mappedTypesArraysTuples.types new file mode 100644 index 0000000000000..83089828b4a09 --- /dev/null +++ b/tests/baselines/reference/mappedTypesArraysTuples.types @@ -0,0 +1,257 @@ +=== tests/cases/conformance/types/mapped/mappedTypesArraysTuples.ts === +type Box = { value: T }; +>Box : Box +>T : T +>value : T +>T : T + +type Boxified = { [P in keyof T]: Box }; +>Boxified : Boxified +>T : T +>P : P +>T : T +>Box : Box +>T : T +>P : P + +type T00 = Boxified<[number, string?, ...boolean[]]>; +>T00 : [Box, Box?, ...Box[]] +>Boxified : Boxified + +type T01 = Partial<[number, string?, ...boolean[]]>; +>T01 : [(number | undefined)?, (string | undefined)?, ...(boolean | undefined)[]] +>Partial : Partial + +type T02 = Required<[number, string?, ...boolean[]]>; +>T02 : [number, string, ...boolean[]] +>Required : Required + +type T10 = Boxified; +>T10 : Box[] +>Boxified : Boxified + +type T11 = Partial; +>T11 : (string | undefined)[] +>Partial : Partial + +type T12 = Required; +>T12 : string[] +>Required : Required + +type T13 = Boxified>; +>T13 : ReadonlyArray> +>Boxified : Boxified +>ReadonlyArray : ReadonlyArray + +type T14 = Partial>; +>T14 : ReadonlyArray +>Partial : Partial +>ReadonlyArray : ReadonlyArray + +type T15 = Required>; +>T15 : ReadonlyArray +>Required : Required +>ReadonlyArray : ReadonlyArray + +type T20 = Boxified<(string | undefined)[]>; +>T20 : Box[] +>Boxified : Boxified + +type T21 = Partial<(string | undefined)[]>; +>T21 : (string | undefined)[] +>Partial : Partial + +type T22 = Required<(string | undefined)[]>; +>T22 : string[] +>Required : Required + +type T23 = Boxified>; +>T23 : ReadonlyArray> +>Boxified : Boxified +>ReadonlyArray : ReadonlyArray + +type T24 = Partial>; +>T24 : ReadonlyArray +>Partial : Partial +>ReadonlyArray : ReadonlyArray + +type T25 = Required>; +>T25 : ReadonlyArray +>Required : Required +>ReadonlyArray : ReadonlyArray + +type T30 = Boxified>; +>T30 : Box[] +>Boxified : Boxified +>Partial : Partial + +type T31 = Partial>; +>T31 : (Box | undefined)[] +>Partial : Partial +>Boxified : Boxified + +type A = { a: string }; +>A : A +>a : string + +type B = { b: string }; +>B : B +>b : string + +type T40 = Boxified | [A, B] | string | string[]>; +>T40 : string | Box[] | Boxified | Box[] | ReadonlyArray> | [Box, Box] +>Boxified : Boxified +>A : A +>A : A +>ReadonlyArray : ReadonlyArray +>A : A +>A : A +>B : B + +declare function unboxify(x: Boxified): T; +>unboxify : (x: Boxified) => T +>T : T +>x : Boxified +>Boxified : Boxified +>T : T +>T : T + +declare let x10: [Box, Box, ...Box[]]; +>x10 : [Box, Box, ...Box[]] +>Box : Box +>Box : Box +>Box : Box + +let y10 = unboxify(x10); +>y10 : [number, string, ...boolean[]] +>unboxify(x10) : [number, string, ...boolean[]] +>unboxify : (x: Boxified) => T +>x10 : [Box, Box, ...Box[]] + +declare let x11: Box[]; +>x11 : Box[] +>Box : Box + +let y11 = unboxify(x11); +>y11 : number[] +>unboxify(x11) : number[] +>unboxify : (x: Boxified) => T +>x11 : Box[] + +declare let x12: { a: Box, b: Box }; +>x12 : { a: Box; b: Box; } +>a : Box +>Box : Box +>b : Box +>Box : Box + +let y12 = unboxify(x12); +>y12 : { a: number; b: string[]; } +>unboxify(x12) : { a: number; b: string[]; } +>unboxify : (x: Boxified) => T +>x12 : { a: Box; b: Box; } + +declare function nonpartial(x: Partial): T; +>nonpartial : (x: Partial) => T +>T : T +>x : Partial +>Partial : Partial +>T : T +>T : T + +declare let x20: [number | undefined, string?, ...boolean[]]; +>x20 : [number | undefined, (string | undefined)?, ...boolean[]] + +let y20 = nonpartial(x20); +>y20 : [number, string, ...boolean[]] +>nonpartial(x20) : [number, string, ...boolean[]] +>nonpartial : (x: Partial) => T +>x20 : [number | undefined, (string | undefined)?, ...boolean[]] + +declare let x21: (number | undefined)[]; +>x21 : (number | undefined)[] + +let y21 = nonpartial(x21); +>y21 : number[] +>nonpartial(x21) : number[] +>nonpartial : (x: Partial) => T +>x21 : (number | undefined)[] + +declare let x22: { a: number | undefined, b?: string[] }; +>x22 : { a: number | undefined; b?: string[] | undefined; } +>a : number | undefined +>b : string[] | undefined + +let y22 = nonpartial(x22); +>y22 : { a: number; b: string[]; } +>nonpartial(x22) : { a: number; b: string[]; } +>nonpartial : (x: Partial) => T +>x22 : { a: number | undefined; b?: string[] | undefined; } + +type Awaited = T extends PromiseLike ? U : T; +>Awaited : Awaited +>T : T +>T : T +>PromiseLike : PromiseLike +>U : U +>U : U +>T : T + +type Awaitified = { [P in keyof T]: Awaited }; +>Awaitified : Awaitified +>T : T +>P : P +>T : T +>Awaited : Awaited +>T : T +>P : P + +declare function all(...values: T): Promise>; +>all : (...values: T) => Promise> +>T : T +>values : T +>T : T +>Promise : Promise +>Awaitified : Awaitified +>T : T + +function f1(a: number, b: Promise, c: string[], d: Promise) { +>f1 : (a: number, b: Promise, c: string[], d: Promise) => void +>a : number +>b : Promise +>Promise : Promise +>c : string[] +>d : Promise +>Promise : Promise + + let x1 = all(a); +>x1 : Promise<[number]> +>all(a) : Promise<[number]> +>all : (...values: T) => Promise> +>a : number + + let x2 = all(a, b); +>x2 : Promise<[number, number]> +>all(a, b) : Promise<[number, number]> +>all : (...values: T) => Promise> +>a : number +>b : Promise + + let x3 = all(a, b, c); +>x3 : Promise<[number, number, string[]]> +>all(a, b, c) : Promise<[number, number, string[]]> +>all : (...values: T) => Promise> +>a : number +>b : Promise +>c : string[] + + let x4 = all(a, b, c, d); +>x4 : Promise<[number, number, string[], string[]]> +>all(a, b, c, d) : Promise<[number, number, string[], string[]]> +>all : (...values: T) => Promise> +>a : number +>b : Promise +>c : string[] +>d : Promise +} +