From ac8be7cd07f765389868f9491ea40c85ee371106 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Oct 2021 00:35:08 +0000 Subject: [PATCH 01/17] Added/updated tests. --- tests/cases/compiler/promiseAllOnAny01.ts | 7 +++++++ .../types/mapped/mappedTypeWithAny.ts | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 tests/cases/compiler/promiseAllOnAny01.ts diff --git a/tests/cases/compiler/promiseAllOnAny01.ts b/tests/cases/compiler/promiseAllOnAny01.ts new file mode 100644 index 0000000000000..be31ad137e421 --- /dev/null +++ b/tests/cases/compiler/promiseAllOnAny01.ts @@ -0,0 +1,7 @@ +// @noEmit: true + +async function foo(x: any) { + let abc = await Promise.all(x); + let result: any[] = abc; + return result; +} \ No newline at end of file diff --git a/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts index f8b6f8a39b7d2..952a72013935e 100644 --- a/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts +++ b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts @@ -25,3 +25,19 @@ for (let id in z) { let data = z[id]; let x = data.notAValue; // Error } + +// Issue #46169. +// We want mapped types whose constraint is `keyof T` to +// map over `any` differently, depending on whether `T` +// is constrained to an array-like type. +type Arrayish = { [K in keyof T]: T[K] }; +type Objectish = { [K in keyof T]: T[K] }; + +function bar(arrayish: Arrayish, objectish: Objectish) { + let arr: any[]; + arr = arrayish; + arr = objectish; +} + +declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; +let abc: any[] = stringifyArray(void 0 as any); \ No newline at end of file From 8741cdf686877e837117fcb7ca6588fef63aaa47 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Oct 2021 00:35:43 +0000 Subject: [PATCH 02/17] Accepted baselines. --- .../reference/mappedTypeWithAny.errors.txt | 28 +++++++++- .../baselines/reference/mappedTypeWithAny.js | 34 ++++++++++++- .../reference/mappedTypeWithAny.symbols | 51 +++++++++++++++++++ .../reference/mappedTypeWithAny.types | 41 +++++++++++++++ .../reference/promiseAllOnAny01.errors.txt | 11 ++++ .../reference/promiseAllOnAny01.symbols | 16 ++++++ .../reference/promiseAllOnAny01.types | 21 ++++++++ 7 files changed, 199 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/promiseAllOnAny01.errors.txt create mode 100644 tests/baselines/reference/promiseAllOnAny01.symbols create mode 100644 tests/baselines/reference/promiseAllOnAny01.types diff --git a/tests/baselines/reference/mappedTypeWithAny.errors.txt b/tests/baselines/reference/mappedTypeWithAny.errors.txt index 0ce53e5044d56..6ca1d18ea5a11 100644 --- a/tests/baselines/reference/mappedTypeWithAny.errors.txt +++ b/tests/baselines/reference/mappedTypeWithAny.errors.txt @@ -1,7 +1,10 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(23,16): error TS2339: Property 'notAValue' does not exist on type 'Data'. +tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(35,5): error TS2740: Type 'Arrayish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. +tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(36,5): error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. +tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(40,5): error TS2740: Type '{ [x: string]: string; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. -==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (1 errors) ==== +==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (4 errors) ==== type Item = { value: string }; type ItemMap = { [P in keyof T]: Item }; @@ -28,4 +31,25 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(23,16): error TS2339: ~~~~~~~~~ !!! error TS2339: Property 'notAValue' does not exist on type 'Data'. } - \ No newline at end of file + + // Issue #46169. + // We want mapped types whose constraint is `keyof T` to + // map over `any` differently, depending on whether `T` + // is constrained to an array-like type. + type Arrayish = { [K in keyof T]: T[K] }; + type Objectish = { [K in keyof T]: T[K] }; + + function bar(arrayish: Arrayish, objectish: Objectish) { + let arr: any[]; + arr = arrayish; + ~~~ +!!! error TS2740: Type 'Arrayish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. + arr = objectish; + ~~~ +!!! error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. + } + + declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; + let abc: any[] = stringifyArray(void 0 as any); + ~~~ +!!! error TS2740: Type '{ [x: string]: string; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAny.js b/tests/baselines/reference/mappedTypeWithAny.js index 1e5c662310ca8..bcf557904f83b 100644 --- a/tests/baselines/reference/mappedTypeWithAny.js +++ b/tests/baselines/reference/mappedTypeWithAny.js @@ -23,7 +23,22 @@ for (let id in z) { let data = z[id]; let x = data.notAValue; // Error } - + +// Issue #46169. +// We want mapped types whose constraint is `keyof T` to +// map over `any` differently, depending on whether `T` +// is constrained to an array-like type. +type Arrayish = { [K in keyof T]: T[K] }; +type Objectish = { [K in keyof T]: T[K] }; + +function bar(arrayish: Arrayish, objectish: Objectish) { + let arr: any[]; + arr = arrayish; + arr = objectish; +} + +declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; +let abc: any[] = stringifyArray(void 0 as any); //// [mappedTypeWithAny.js] "use strict"; @@ -31,6 +46,12 @@ for (var id in z) { var data = z[id]; var x = data.notAValue; // Error } +function bar(arrayish, objectish) { + var arr; + arr = arrayish; + arr = objectish; +} +var abc = stringifyArray(void 0); //// [mappedTypeWithAny.d.ts] @@ -58,3 +79,14 @@ declare type StrictDataMap = { [P in keyof T]: Data; }; declare let z: StrictDataMap; +declare type Arrayish = { + [K in keyof T]: T[K]; +}; +declare type Objectish = { + [K in keyof T]: T[K]; +}; +declare function bar(arrayish: Arrayish, objectish: Objectish): void; +declare function stringifyArray(arr: T): { + -readonly [K in keyof T]: string; +}; +declare let abc: any[]; diff --git a/tests/baselines/reference/mappedTypeWithAny.symbols b/tests/baselines/reference/mappedTypeWithAny.symbols index 2c204d4b1ef27..76379520b3dfe 100644 --- a/tests/baselines/reference/mappedTypeWithAny.symbols +++ b/tests/baselines/reference/mappedTypeWithAny.symbols @@ -69,3 +69,54 @@ for (let id in z) { >data : Symbol(data, Decl(mappedTypeWithAny.ts, 21, 5)) } +// Issue #46169. +// We want mapped types whose constraint is `keyof T` to +// map over `any` differently, depending on whether `T` +// is constrained to an array-like type. +type Arrayish = { [K in keyof T]: T[K] }; +>Arrayish : Symbol(Arrayish, Decl(mappedTypeWithAny.ts, 23, 1)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 29, 14)) +>K : Symbol(K, Decl(mappedTypeWithAny.ts, 29, 40)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 29, 14)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 29, 14)) +>K : Symbol(K, Decl(mappedTypeWithAny.ts, 29, 40)) + +type Objectish = { [K in keyof T]: T[K] }; +>Objectish : Symbol(Objectish, Decl(mappedTypeWithAny.ts, 29, 62)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 30, 15)) +>K : Symbol(K, Decl(mappedTypeWithAny.ts, 30, 39)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 30, 15)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 30, 15)) +>K : Symbol(K, Decl(mappedTypeWithAny.ts, 30, 39)) + +function bar(arrayish: Arrayish, objectish: Objectish) { +>bar : Symbol(bar, Decl(mappedTypeWithAny.ts, 30, 61)) +>arrayish : Symbol(arrayish, Decl(mappedTypeWithAny.ts, 32, 13)) +>Arrayish : Symbol(Arrayish, Decl(mappedTypeWithAny.ts, 23, 1)) +>objectish : Symbol(objectish, Decl(mappedTypeWithAny.ts, 32, 37)) +>Objectish : Symbol(Objectish, Decl(mappedTypeWithAny.ts, 29, 62)) + + let arr: any[]; +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 33, 7)) + + arr = arrayish; +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 33, 7)) +>arrayish : Symbol(arrayish, Decl(mappedTypeWithAny.ts, 32, 13)) + + arr = objectish; +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 33, 7)) +>objectish : Symbol(objectish, Decl(mappedTypeWithAny.ts, 32, 37)) +} + +declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; +>stringifyArray : Symbol(stringifyArray, Decl(mappedTypeWithAny.ts, 36, 1)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 38, 32)) +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 38, 58)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 38, 32)) +>K : Symbol(K, Decl(mappedTypeWithAny.ts, 38, 80)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 38, 32)) + +let abc: any[] = stringifyArray(void 0 as any); +>abc : Symbol(abc, Decl(mappedTypeWithAny.ts, 39, 3)) +>stringifyArray : Symbol(stringifyArray, Decl(mappedTypeWithAny.ts, 36, 1)) + diff --git a/tests/baselines/reference/mappedTypeWithAny.types b/tests/baselines/reference/mappedTypeWithAny.types index c95a17ab43b51..f9676f81320f1 100644 --- a/tests/baselines/reference/mappedTypeWithAny.types +++ b/tests/baselines/reference/mappedTypeWithAny.types @@ -56,3 +56,44 @@ for (let id in z) { >notAValue : any } +// Issue #46169. +// We want mapped types whose constraint is `keyof T` to +// map over `any` differently, depending on whether `T` +// is constrained to an array-like type. +type Arrayish = { [K in keyof T]: T[K] }; +>Arrayish : Arrayish + +type Objectish = { [K in keyof T]: T[K] }; +>Objectish : Objectish + +function bar(arrayish: Arrayish, objectish: Objectish) { +>bar : (arrayish: Arrayish, objectish: Objectish) => void +>arrayish : Arrayish +>objectish : Objectish + + let arr: any[]; +>arr : any[] + + arr = arrayish; +>arr = arrayish : Arrayish +>arr : any[] +>arrayish : Arrayish + + arr = objectish; +>arr = objectish : Objectish +>arr : any[] +>objectish : Objectish +} + +declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; +>stringifyArray : (arr: T) => { -readonly [K in keyof T]: string; } +>arr : T + +let abc: any[] = stringifyArray(void 0 as any); +>abc : any[] +>stringifyArray(void 0 as any) : { [x: string]: string; } +>stringifyArray : (arr: T) => { -readonly [K in keyof T]: string; } +>void 0 as any : any +>void 0 : undefined +>0 : 0 + diff --git a/tests/baselines/reference/promiseAllOnAny01.errors.txt b/tests/baselines/reference/promiseAllOnAny01.errors.txt new file mode 100644 index 0000000000000..477ef3770bf23 --- /dev/null +++ b/tests/baselines/reference/promiseAllOnAny01.errors.txt @@ -0,0 +1,11 @@ +tests/cases/compiler/promiseAllOnAny01.ts(2,21): error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. + + +==== tests/cases/compiler/promiseAllOnAny01.ts (1 errors) ==== + async function foo(x: any) { + let abc = await Promise.all(x); + ~~~~~~~ +!!! error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. + let result: any[] = abc; + return result; + } \ No newline at end of file diff --git a/tests/baselines/reference/promiseAllOnAny01.symbols b/tests/baselines/reference/promiseAllOnAny01.symbols new file mode 100644 index 0000000000000..597378def6d3d --- /dev/null +++ b/tests/baselines/reference/promiseAllOnAny01.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/promiseAllOnAny01.ts === +async function foo(x: any) { +>foo : Symbol(foo, Decl(promiseAllOnAny01.ts, 0, 0)) +>x : Symbol(x, Decl(promiseAllOnAny01.ts, 0, 19)) + + let abc = await Promise.all(x); +>abc : Symbol(abc, Decl(promiseAllOnAny01.ts, 1, 7)) +>x : Symbol(x, Decl(promiseAllOnAny01.ts, 0, 19)) + + let result: any[] = abc; +>result : Symbol(result, Decl(promiseAllOnAny01.ts, 2, 7)) +>abc : Symbol(abc, Decl(promiseAllOnAny01.ts, 1, 7)) + + return result; +>result : Symbol(result, Decl(promiseAllOnAny01.ts, 2, 7)) +} diff --git a/tests/baselines/reference/promiseAllOnAny01.types b/tests/baselines/reference/promiseAllOnAny01.types new file mode 100644 index 0000000000000..dba7c1d46cfb0 --- /dev/null +++ b/tests/baselines/reference/promiseAllOnAny01.types @@ -0,0 +1,21 @@ +=== tests/cases/compiler/promiseAllOnAny01.ts === +async function foo(x: any) { +>foo : (x: any) => Promise +>x : any + + let abc = await Promise.all(x); +>abc : any +>await Promise.all(x) : any +>Promise.all(x) : any +>Promise.all : any +>Promise : any +>all : any +>x : any + + let result: any[] = abc; +>result : any[] +>abc : any + + return result; +>result : any[] +} From 151e1a6e4d3f6aeafad71df5c71fdf78a22e1da2 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Oct 2021 01:04:48 +0000 Subject: [PATCH 03/17] Update test. --- tests/cases/compiler/promiseAllOnAny01.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/cases/compiler/promiseAllOnAny01.ts b/tests/cases/compiler/promiseAllOnAny01.ts index be31ad137e421..75d3b2d09026d 100644 --- a/tests/cases/compiler/promiseAllOnAny01.ts +++ b/tests/cases/compiler/promiseAllOnAny01.ts @@ -1,4 +1,5 @@ // @noEmit: true +// @lib: es5,es2015.promise async function foo(x: any) { let abc = await Promise.all(x); From a27f15d14082ea7440ed5122c0cf20edff07cc10 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Oct 2021 01:08:52 +0000 Subject: [PATCH 04/17] Update instantiateMappedType to work specially when 'any' replaced an array. --- src/compiler/checker.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1af122e4e3b4e..1725dcc607637 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16515,7 +16515,8 @@ namespace ts { return mapTypeWithAlias(getReducedType(mappedTypeVariable), t => { if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t)) { if (!type.declaration.nameType) { - if (isArrayType(t)) { + let constraint; + if (isArrayType(t) || (t.flags & TypeFlags.Any) && (constraint = getConstraintOfTypeParameter(typeVariable)) && (isArrayType(constraint) || isTupleType(constraint))) { return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); } if (isGenericTupleType(t)) { From d8844a7967281c61f7a6907aebb4fe6195d054e8 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Oct 2021 01:09:10 +0000 Subject: [PATCH 05/17] Accepted baselines. --- .../reference/mappedTypeWithAny.errors.txt | 10 ++-------- tests/baselines/reference/mappedTypeWithAny.types | 8 ++++---- .../reference/promiseAllOnAny01.errors.txt | 6 +++--- .../baselines/reference/promiseAllOnAny01.symbols | 3 +++ tests/baselines/reference/promiseAllOnAny01.types | 14 +++++++------- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/tests/baselines/reference/mappedTypeWithAny.errors.txt b/tests/baselines/reference/mappedTypeWithAny.errors.txt index 6ca1d18ea5a11..cc71a42b4463f 100644 --- a/tests/baselines/reference/mappedTypeWithAny.errors.txt +++ b/tests/baselines/reference/mappedTypeWithAny.errors.txt @@ -1,10 +1,8 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(23,16): error TS2339: Property 'notAValue' does not exist on type 'Data'. -tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(35,5): error TS2740: Type 'Arrayish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(36,5): error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. -tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(40,5): error TS2740: Type '{ [x: string]: string; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. -==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (4 errors) ==== +==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (2 errors) ==== type Item = { value: string }; type ItemMap = { [P in keyof T]: Item }; @@ -42,14 +40,10 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(40,5): error TS2740: T function bar(arrayish: Arrayish, objectish: Objectish) { let arr: any[]; arr = arrayish; - ~~~ -!!! error TS2740: Type 'Arrayish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. arr = objectish; ~~~ !!! error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. } declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; - let abc: any[] = stringifyArray(void 0 as any); - ~~~ -!!! error TS2740: Type '{ [x: string]: string; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. \ No newline at end of file + let abc: any[] = stringifyArray(void 0 as any); \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAny.types b/tests/baselines/reference/mappedTypeWithAny.types index f9676f81320f1..21150c71dc308 100644 --- a/tests/baselines/reference/mappedTypeWithAny.types +++ b/tests/baselines/reference/mappedTypeWithAny.types @@ -68,16 +68,16 @@ type Objectish = { [K in keyof T]: T[K] }; function bar(arrayish: Arrayish, objectish: Objectish) { >bar : (arrayish: Arrayish, objectish: Objectish) => void ->arrayish : Arrayish +>arrayish : any[] >objectish : Objectish let arr: any[]; >arr : any[] arr = arrayish; ->arr = arrayish : Arrayish +>arr = arrayish : any[] >arr : any[] ->arrayish : Arrayish +>arrayish : any[] arr = objectish; >arr = objectish : Objectish @@ -91,7 +91,7 @@ declare function stringifyArray(arr: T): { -readonly [ let abc: any[] = stringifyArray(void 0 as any); >abc : any[] ->stringifyArray(void 0 as any) : { [x: string]: string; } +>stringifyArray(void 0 as any) : string[] >stringifyArray : (arr: T) => { -readonly [K in keyof T]: string; } >void 0 as any : any >void 0 : undefined diff --git a/tests/baselines/reference/promiseAllOnAny01.errors.txt b/tests/baselines/reference/promiseAllOnAny01.errors.txt index 477ef3770bf23..7007a5a6d01a9 100644 --- a/tests/baselines/reference/promiseAllOnAny01.errors.txt +++ b/tests/baselines/reference/promiseAllOnAny01.errors.txt @@ -1,11 +1,11 @@ -tests/cases/compiler/promiseAllOnAny01.ts(2,21): error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. +tests/cases/compiler/promiseAllOnAny01.ts(3,9): error TS2740: Type '{ [x: string]: any; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. ==== tests/cases/compiler/promiseAllOnAny01.ts (1 errors) ==== async function foo(x: any) { let abc = await Promise.all(x); - ~~~~~~~ -!!! error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. let result: any[] = abc; + ~~~~~~ +!!! error TS2740: Type '{ [x: string]: any; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. return result; } \ No newline at end of file diff --git a/tests/baselines/reference/promiseAllOnAny01.symbols b/tests/baselines/reference/promiseAllOnAny01.symbols index 597378def6d3d..3a31306889f2b 100644 --- a/tests/baselines/reference/promiseAllOnAny01.symbols +++ b/tests/baselines/reference/promiseAllOnAny01.symbols @@ -5,6 +5,9 @@ async function foo(x: any) { let abc = await Promise.all(x); >abc : Symbol(abc, Decl(promiseAllOnAny01.ts, 1, 7)) +>Promise.all : Symbol(PromiseConstructor.all, Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>all : Symbol(PromiseConstructor.all, Decl(lib.es2015.promise.d.ts, --, --)) >x : Symbol(x, Decl(promiseAllOnAny01.ts, 0, 19)) let result: any[] = abc; diff --git a/tests/baselines/reference/promiseAllOnAny01.types b/tests/baselines/reference/promiseAllOnAny01.types index dba7c1d46cfb0..e3824804b0952 100644 --- a/tests/baselines/reference/promiseAllOnAny01.types +++ b/tests/baselines/reference/promiseAllOnAny01.types @@ -4,17 +4,17 @@ async function foo(x: any) { >x : any let abc = await Promise.all(x); ->abc : any ->await Promise.all(x) : any ->Promise.all(x) : any ->Promise.all : any ->Promise : any ->all : any +>abc : { [x: string]: any; } +>await Promise.all(x) : { [x: string]: any; } +>Promise.all(x) : Promise<{ [x: string]: any; }> +>Promise.all : (values: T) => Promise<{ -readonly [P in keyof T]: Awaited; }> +>Promise : PromiseConstructor +>all : (values: T) => Promise<{ -readonly [P in keyof T]: Awaited; }> >x : any let result: any[] = abc; >result : any[] ->abc : any +>abc : { [x: string]: any; } return result; >result : any[] From eebb1d46196155d337250fa44dcb67a3fc6c92b7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Oct 2021 01:11:03 +0000 Subject: [PATCH 06/17] Ensure check works when constraint is a union of arrayish types, just like in `Promise.all`. --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1725dcc607637..043745c7c5c28 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16516,7 +16516,7 @@ namespace ts { if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t)) { if (!type.declaration.nameType) { let constraint; - if (isArrayType(t) || (t.flags & TypeFlags.Any) && (constraint = getConstraintOfTypeParameter(typeVariable)) && (isArrayType(constraint) || isTupleType(constraint))) { + if (isArrayType(t) || (t.flags & TypeFlags.Any) && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, or(isArrayType, isTupleType))) { return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); } if (isGenericTupleType(t)) { From 99d9b5657d0bda1115609f07cfb9531cb8040318 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Oct 2021 01:14:28 +0000 Subject: [PATCH 07/17] Accepted baselines. --- .../baselines/reference/promiseAllOnAny01.errors.txt | 11 ----------- tests/baselines/reference/promiseAllOnAny01.types | 8 ++++---- 2 files changed, 4 insertions(+), 15 deletions(-) delete mode 100644 tests/baselines/reference/promiseAllOnAny01.errors.txt diff --git a/tests/baselines/reference/promiseAllOnAny01.errors.txt b/tests/baselines/reference/promiseAllOnAny01.errors.txt deleted file mode 100644 index 7007a5a6d01a9..0000000000000 --- a/tests/baselines/reference/promiseAllOnAny01.errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -tests/cases/compiler/promiseAllOnAny01.ts(3,9): error TS2740: Type '{ [x: string]: any; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. - - -==== tests/cases/compiler/promiseAllOnAny01.ts (1 errors) ==== - async function foo(x: any) { - let abc = await Promise.all(x); - let result: any[] = abc; - ~~~~~~ -!!! error TS2740: Type '{ [x: string]: any; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. - return result; - } \ No newline at end of file diff --git a/tests/baselines/reference/promiseAllOnAny01.types b/tests/baselines/reference/promiseAllOnAny01.types index e3824804b0952..c0431773e66d5 100644 --- a/tests/baselines/reference/promiseAllOnAny01.types +++ b/tests/baselines/reference/promiseAllOnAny01.types @@ -4,9 +4,9 @@ async function foo(x: any) { >x : any let abc = await Promise.all(x); ->abc : { [x: string]: any; } ->await Promise.all(x) : { [x: string]: any; } ->Promise.all(x) : Promise<{ [x: string]: any; }> +>abc : any[] +>await Promise.all(x) : any[] +>Promise.all(x) : Promise >Promise.all : (values: T) => Promise<{ -readonly [P in keyof T]: Awaited; }> >Promise : PromiseConstructor >all : (values: T) => Promise<{ -readonly [P in keyof T]: Awaited; }> @@ -14,7 +14,7 @@ async function foo(x: any) { let result: any[] = abc; >result : any[] ->abc : { [x: string]: any; } +>abc : any[] return result; >result : any[] From 9ff4385deadec88a97e21ac27dd891d78a63ec30 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Oct 2021 19:13:34 +0000 Subject: [PATCH 08/17] Update test for indirect instantiation of a mapped type. --- .../conformance/types/mapped/mappedTypeWithAny.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts index 952a72013935e..1f4d1f4f82bd3 100644 --- a/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts +++ b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts @@ -29,14 +29,21 @@ for (let id in z) { // Issue #46169. // We want mapped types whose constraint is `keyof T` to // map over `any` differently, depending on whether `T` -// is constrained to an array-like type. +// is constrained to array and tuple types. type Arrayish = { [K in keyof T]: T[K] }; type Objectish = { [K in keyof T]: T[K] }; -function bar(arrayish: Arrayish, objectish: Objectish) { +// When a mapped type whose constraint is `keyof T` is instantiated, +// `T` may be instantiated with a `U` which is constrained to +// array and tuple types. When `U` is later instantiated with `any`, +// the result should also be some sort of array. +type IndirectArrayish = Objectish; + +function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayish: IndirectArrayish) { let arr: any[]; arr = arrayish; arr = objectish; + arr = indirectArrayish; } declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; From 6aa36700153d85d21849d00aca54f18531786bd9 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Oct 2021 19:13:47 +0000 Subject: [PATCH 09/17] Accepted baselines. --- .../reference/mappedTypeWithAny.errors.txt | 18 +++++-- .../baselines/reference/mappedTypeWithAny.js | 17 ++++-- .../reference/mappedTypeWithAny.symbols | 52 ++++++++++++------- .../reference/mappedTypeWithAny.types | 19 +++++-- 4 files changed, 77 insertions(+), 29 deletions(-) diff --git a/tests/baselines/reference/mappedTypeWithAny.errors.txt b/tests/baselines/reference/mappedTypeWithAny.errors.txt index cc71a42b4463f..05e92a4c9a7b3 100644 --- a/tests/baselines/reference/mappedTypeWithAny.errors.txt +++ b/tests/baselines/reference/mappedTypeWithAny.errors.txt @@ -1,8 +1,9 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(23,16): error TS2339: Property 'notAValue' does not exist on type 'Data'. -tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(36,5): error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. +tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(42,5): error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. +tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(43,5): error TS2322: Type 'Objectish' is not assignable to type 'any[]'. -==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (2 errors) ==== +==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (3 errors) ==== type Item = { value: string }; type ItemMap = { [P in keyof T]: Item }; @@ -33,16 +34,25 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(36,5): error TS2740: T // Issue #46169. // We want mapped types whose constraint is `keyof T` to // map over `any` differently, depending on whether `T` - // is constrained to an array-like type. + // is constrained to array and tuple types. type Arrayish = { [K in keyof T]: T[K] }; type Objectish = { [K in keyof T]: T[K] }; - function bar(arrayish: Arrayish, objectish: Objectish) { + // When a mapped type whose constraint is `keyof T` is instantiated, + // `T` may be instantiated with a `U` which is constrained to + // array and tuple types. When `U` is later instantiated with `any`, + // the result should also be some sort of array. + type IndirectArrayish = Objectish; + + function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayish: IndirectArrayish) { let arr: any[]; arr = arrayish; arr = objectish; ~~~ !!! error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. + arr = indirectArrayish; + ~~~ +!!! error TS2322: Type 'Objectish' is not assignable to type 'any[]'. } declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; diff --git a/tests/baselines/reference/mappedTypeWithAny.js b/tests/baselines/reference/mappedTypeWithAny.js index bcf557904f83b..97945d71f5702 100644 --- a/tests/baselines/reference/mappedTypeWithAny.js +++ b/tests/baselines/reference/mappedTypeWithAny.js @@ -27,14 +27,21 @@ for (let id in z) { // Issue #46169. // We want mapped types whose constraint is `keyof T` to // map over `any` differently, depending on whether `T` -// is constrained to an array-like type. +// is constrained to array and tuple types. type Arrayish = { [K in keyof T]: T[K] }; type Objectish = { [K in keyof T]: T[K] }; -function bar(arrayish: Arrayish, objectish: Objectish) { +// When a mapped type whose constraint is `keyof T` is instantiated, +// `T` may be instantiated with a `U` which is constrained to +// array and tuple types. When `U` is later instantiated with `any`, +// the result should also be some sort of array. +type IndirectArrayish = Objectish; + +function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayish: IndirectArrayish) { let arr: any[]; arr = arrayish; arr = objectish; + arr = indirectArrayish; } declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; @@ -46,10 +53,11 @@ for (var id in z) { var data = z[id]; var x = data.notAValue; // Error } -function bar(arrayish, objectish) { +function bar(arrayish, objectish, indirectArrayish) { var arr; arr = arrayish; arr = objectish; + arr = indirectArrayish; } var abc = stringifyArray(void 0); @@ -85,7 +93,8 @@ declare type Arrayish = { declare type Objectish = { [K in keyof T]: T[K]; }; -declare function bar(arrayish: Arrayish, objectish: Objectish): void; +declare type IndirectArrayish = Objectish; +declare function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayish: IndirectArrayish): void; declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string; }; diff --git a/tests/baselines/reference/mappedTypeWithAny.symbols b/tests/baselines/reference/mappedTypeWithAny.symbols index 76379520b3dfe..28ccff258d729 100644 --- a/tests/baselines/reference/mappedTypeWithAny.symbols +++ b/tests/baselines/reference/mappedTypeWithAny.symbols @@ -72,7 +72,7 @@ for (let id in z) { // Issue #46169. // We want mapped types whose constraint is `keyof T` to // map over `any` differently, depending on whether `T` -// is constrained to an array-like type. +// is constrained to array and tuple types. type Arrayish = { [K in keyof T]: T[K] }; >Arrayish : Symbol(Arrayish, Decl(mappedTypeWithAny.ts, 23, 1)) >T : Symbol(T, Decl(mappedTypeWithAny.ts, 29, 14)) @@ -89,34 +89,50 @@ type Objectish = { [K in keyof T]: T[K] }; >T : Symbol(T, Decl(mappedTypeWithAny.ts, 30, 15)) >K : Symbol(K, Decl(mappedTypeWithAny.ts, 30, 39)) -function bar(arrayish: Arrayish, objectish: Objectish) { ->bar : Symbol(bar, Decl(mappedTypeWithAny.ts, 30, 61)) ->arrayish : Symbol(arrayish, Decl(mappedTypeWithAny.ts, 32, 13)) +// When a mapped type whose constraint is `keyof T` is instantiated, +// `T` may be instantiated with a `U` which is constrained to +// array and tuple types. When `U` is later instantiated with `any`, +// the result should also be some sort of array. +type IndirectArrayish = Objectish; +>IndirectArrayish : Symbol(IndirectArrayish, Decl(mappedTypeWithAny.ts, 30, 61)) +>U : Symbol(U, Decl(mappedTypeWithAny.ts, 36, 22)) +>Objectish : Symbol(Objectish, Decl(mappedTypeWithAny.ts, 29, 62)) +>U : Symbol(U, Decl(mappedTypeWithAny.ts, 36, 22)) + +function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayish: IndirectArrayish) { +>bar : Symbol(bar, Decl(mappedTypeWithAny.ts, 36, 58)) +>arrayish : Symbol(arrayish, Decl(mappedTypeWithAny.ts, 38, 13)) >Arrayish : Symbol(Arrayish, Decl(mappedTypeWithAny.ts, 23, 1)) ->objectish : Symbol(objectish, Decl(mappedTypeWithAny.ts, 32, 37)) +>objectish : Symbol(objectish, Decl(mappedTypeWithAny.ts, 38, 37)) >Objectish : Symbol(Objectish, Decl(mappedTypeWithAny.ts, 29, 62)) +>indirectArrayish : Symbol(indirectArrayish, Decl(mappedTypeWithAny.ts, 38, 64)) +>IndirectArrayish : Symbol(IndirectArrayish, Decl(mappedTypeWithAny.ts, 30, 61)) let arr: any[]; ->arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 33, 7)) +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 39, 7)) arr = arrayish; ->arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 33, 7)) ->arrayish : Symbol(arrayish, Decl(mappedTypeWithAny.ts, 32, 13)) +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 39, 7)) +>arrayish : Symbol(arrayish, Decl(mappedTypeWithAny.ts, 38, 13)) arr = objectish; ->arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 33, 7)) ->objectish : Symbol(objectish, Decl(mappedTypeWithAny.ts, 32, 37)) +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 39, 7)) +>objectish : Symbol(objectish, Decl(mappedTypeWithAny.ts, 38, 37)) + + arr = indirectArrayish; +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 39, 7)) +>indirectArrayish : Symbol(indirectArrayish, Decl(mappedTypeWithAny.ts, 38, 64)) } declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; ->stringifyArray : Symbol(stringifyArray, Decl(mappedTypeWithAny.ts, 36, 1)) ->T : Symbol(T, Decl(mappedTypeWithAny.ts, 38, 32)) ->arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 38, 58)) ->T : Symbol(T, Decl(mappedTypeWithAny.ts, 38, 32)) ->K : Symbol(K, Decl(mappedTypeWithAny.ts, 38, 80)) ->T : Symbol(T, Decl(mappedTypeWithAny.ts, 38, 32)) +>stringifyArray : Symbol(stringifyArray, Decl(mappedTypeWithAny.ts, 43, 1)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 45, 32)) +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 45, 58)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 45, 32)) +>K : Symbol(K, Decl(mappedTypeWithAny.ts, 45, 80)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 45, 32)) let abc: any[] = stringifyArray(void 0 as any); ->abc : Symbol(abc, Decl(mappedTypeWithAny.ts, 39, 3)) ->stringifyArray : Symbol(stringifyArray, Decl(mappedTypeWithAny.ts, 36, 1)) +>abc : Symbol(abc, Decl(mappedTypeWithAny.ts, 46, 3)) +>stringifyArray : Symbol(stringifyArray, Decl(mappedTypeWithAny.ts, 43, 1)) diff --git a/tests/baselines/reference/mappedTypeWithAny.types b/tests/baselines/reference/mappedTypeWithAny.types index 21150c71dc308..f36d357325e12 100644 --- a/tests/baselines/reference/mappedTypeWithAny.types +++ b/tests/baselines/reference/mappedTypeWithAny.types @@ -59,17 +59,25 @@ for (let id in z) { // Issue #46169. // We want mapped types whose constraint is `keyof T` to // map over `any` differently, depending on whether `T` -// is constrained to an array-like type. +// is constrained to array and tuple types. type Arrayish = { [K in keyof T]: T[K] }; >Arrayish : Arrayish type Objectish = { [K in keyof T]: T[K] }; >Objectish : Objectish -function bar(arrayish: Arrayish, objectish: Objectish) { ->bar : (arrayish: Arrayish, objectish: Objectish) => void +// When a mapped type whose constraint is `keyof T` is instantiated, +// `T` may be instantiated with a `U` which is constrained to +// array and tuple types. When `U` is later instantiated with `any`, +// the result should also be some sort of array. +type IndirectArrayish = Objectish; +>IndirectArrayish : Objectish + +function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayish: IndirectArrayish) { +>bar : (arrayish: Arrayish, objectish: Objectish, indirectArrayish: IndirectArrayish) => void >arrayish : any[] >objectish : Objectish +>indirectArrayish : Objectish let arr: any[]; >arr : any[] @@ -83,6 +91,11 @@ function bar(arrayish: Arrayish, objectish: Objectish) { >arr = objectish : Objectish >arr : any[] >objectish : Objectish + + arr = indirectArrayish; +>arr = indirectArrayish : Objectish +>arr : any[] +>indirectArrayish : Objectish } declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; From b3ca06442edcf840a3e367c6db1e1a2c12507e48 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 22 Oct 2021 22:33:35 +0000 Subject: [PATCH 10/17] Update test comment. --- tests/cases/conformance/types/mapped/mappedTypeWithAny.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts index 1f4d1f4f82bd3..1140bc35c0c79 100644 --- a/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts +++ b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts @@ -35,8 +35,11 @@ type Objectish = { [K in keyof T]: T[K] }; // When a mapped type whose constraint is `keyof T` is instantiated, // `T` may be instantiated with a `U` which is constrained to -// array and tuple types. When `U` is later instantiated with `any`, -// the result should also be some sort of array. +// array and tuple types. *Ideally*, when `U` is later instantiated with `any`, +// the result should also be some sort of array; however, at the moment we don't seem +// to have an easy way to preserve that information. More than just that, it would be +// inconsistent for two instantiations of `Objectish` to produce different outputs +// depending on the usage-site. As a result, `IndirectArrayish` does not act like `Arrayish`. type IndirectArrayish = Objectish; function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayish: IndirectArrayish) { From 63a6bca65611dba39193364c44c5fb0075378617 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 22 Oct 2021 22:34:50 +0000 Subject: [PATCH 11/17] Accepted baselines. --- .../reference/mappedTypeWithAny.errors.txt | 11 +++-- .../baselines/reference/mappedTypeWithAny.js | 7 ++- .../reference/mappedTypeWithAny.symbols | 49 ++++++++++--------- .../reference/mappedTypeWithAny.types | 7 ++- 4 files changed, 43 insertions(+), 31 deletions(-) diff --git a/tests/baselines/reference/mappedTypeWithAny.errors.txt b/tests/baselines/reference/mappedTypeWithAny.errors.txt index 05e92a4c9a7b3..f611472caed7c 100644 --- a/tests/baselines/reference/mappedTypeWithAny.errors.txt +++ b/tests/baselines/reference/mappedTypeWithAny.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(23,16): error TS2339: Property 'notAValue' does not exist on type 'Data'. -tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(42,5): error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. -tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(43,5): error TS2322: Type 'Objectish' is not assignable to type 'any[]'. +tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(45,5): error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. +tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(46,5): error TS2322: Type 'Objectish' is not assignable to type 'any[]'. ==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (3 errors) ==== @@ -40,8 +40,11 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(43,5): error TS2322: T // When a mapped type whose constraint is `keyof T` is instantiated, // `T` may be instantiated with a `U` which is constrained to - // array and tuple types. When `U` is later instantiated with `any`, - // the result should also be some sort of array. + // array and tuple types. *Ideally*, when `U` is later instantiated with `any`, + // the result should also be some sort of array; however, at the moment we don't seem + // to have an easy way to preserve that information. More than just that, it would be + // inconsistent for two instantiations of `Objectish` to produce different outputs + // depending on the usage-site. As a result, `IndirectArrayish` does not act like `Arrayish`. type IndirectArrayish = Objectish; function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayish: IndirectArrayish) { diff --git a/tests/baselines/reference/mappedTypeWithAny.js b/tests/baselines/reference/mappedTypeWithAny.js index 97945d71f5702..0a683792784c8 100644 --- a/tests/baselines/reference/mappedTypeWithAny.js +++ b/tests/baselines/reference/mappedTypeWithAny.js @@ -33,8 +33,11 @@ type Objectish = { [K in keyof T]: T[K] }; // When a mapped type whose constraint is `keyof T` is instantiated, // `T` may be instantiated with a `U` which is constrained to -// array and tuple types. When `U` is later instantiated with `any`, -// the result should also be some sort of array. +// array and tuple types. *Ideally*, when `U` is later instantiated with `any`, +// the result should also be some sort of array; however, at the moment we don't seem +// to have an easy way to preserve that information. More than just that, it would be +// inconsistent for two instantiations of `Objectish` to produce different outputs +// depending on the usage-site. As a result, `IndirectArrayish` does not act like `Arrayish`. type IndirectArrayish = Objectish; function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayish: IndirectArrayish) { diff --git a/tests/baselines/reference/mappedTypeWithAny.symbols b/tests/baselines/reference/mappedTypeWithAny.symbols index 28ccff258d729..0c4c95f444050 100644 --- a/tests/baselines/reference/mappedTypeWithAny.symbols +++ b/tests/baselines/reference/mappedTypeWithAny.symbols @@ -91,48 +91,51 @@ type Objectish = { [K in keyof T]: T[K] }; // When a mapped type whose constraint is `keyof T` is instantiated, // `T` may be instantiated with a `U` which is constrained to -// array and tuple types. When `U` is later instantiated with `any`, -// the result should also be some sort of array. +// array and tuple types. *Ideally*, when `U` is later instantiated with `any`, +// the result should also be some sort of array; however, at the moment we don't seem +// to have an easy way to preserve that information. More than just that, it would be +// inconsistent for two instantiations of `Objectish` to produce different outputs +// depending on the usage-site. As a result, `IndirectArrayish` does not act like `Arrayish`. type IndirectArrayish = Objectish; >IndirectArrayish : Symbol(IndirectArrayish, Decl(mappedTypeWithAny.ts, 30, 61)) ->U : Symbol(U, Decl(mappedTypeWithAny.ts, 36, 22)) +>U : Symbol(U, Decl(mappedTypeWithAny.ts, 39, 22)) >Objectish : Symbol(Objectish, Decl(mappedTypeWithAny.ts, 29, 62)) ->U : Symbol(U, Decl(mappedTypeWithAny.ts, 36, 22)) +>U : Symbol(U, Decl(mappedTypeWithAny.ts, 39, 22)) function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayish: IndirectArrayish) { ->bar : Symbol(bar, Decl(mappedTypeWithAny.ts, 36, 58)) ->arrayish : Symbol(arrayish, Decl(mappedTypeWithAny.ts, 38, 13)) +>bar : Symbol(bar, Decl(mappedTypeWithAny.ts, 39, 58)) +>arrayish : Symbol(arrayish, Decl(mappedTypeWithAny.ts, 41, 13)) >Arrayish : Symbol(Arrayish, Decl(mappedTypeWithAny.ts, 23, 1)) ->objectish : Symbol(objectish, Decl(mappedTypeWithAny.ts, 38, 37)) +>objectish : Symbol(objectish, Decl(mappedTypeWithAny.ts, 41, 37)) >Objectish : Symbol(Objectish, Decl(mappedTypeWithAny.ts, 29, 62)) ->indirectArrayish : Symbol(indirectArrayish, Decl(mappedTypeWithAny.ts, 38, 64)) +>indirectArrayish : Symbol(indirectArrayish, Decl(mappedTypeWithAny.ts, 41, 64)) >IndirectArrayish : Symbol(IndirectArrayish, Decl(mappedTypeWithAny.ts, 30, 61)) let arr: any[]; ->arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 39, 7)) +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 42, 7)) arr = arrayish; ->arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 39, 7)) ->arrayish : Symbol(arrayish, Decl(mappedTypeWithAny.ts, 38, 13)) +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 42, 7)) +>arrayish : Symbol(arrayish, Decl(mappedTypeWithAny.ts, 41, 13)) arr = objectish; ->arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 39, 7)) ->objectish : Symbol(objectish, Decl(mappedTypeWithAny.ts, 38, 37)) +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 42, 7)) +>objectish : Symbol(objectish, Decl(mappedTypeWithAny.ts, 41, 37)) arr = indirectArrayish; ->arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 39, 7)) ->indirectArrayish : Symbol(indirectArrayish, Decl(mappedTypeWithAny.ts, 38, 64)) +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 42, 7)) +>indirectArrayish : Symbol(indirectArrayish, Decl(mappedTypeWithAny.ts, 41, 64)) } declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; ->stringifyArray : Symbol(stringifyArray, Decl(mappedTypeWithAny.ts, 43, 1)) ->T : Symbol(T, Decl(mappedTypeWithAny.ts, 45, 32)) ->arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 45, 58)) ->T : Symbol(T, Decl(mappedTypeWithAny.ts, 45, 32)) ->K : Symbol(K, Decl(mappedTypeWithAny.ts, 45, 80)) ->T : Symbol(T, Decl(mappedTypeWithAny.ts, 45, 32)) +>stringifyArray : Symbol(stringifyArray, Decl(mappedTypeWithAny.ts, 46, 1)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 48, 32)) +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 48, 58)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 48, 32)) +>K : Symbol(K, Decl(mappedTypeWithAny.ts, 48, 80)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 48, 32)) let abc: any[] = stringifyArray(void 0 as any); ->abc : Symbol(abc, Decl(mappedTypeWithAny.ts, 46, 3)) ->stringifyArray : Symbol(stringifyArray, Decl(mappedTypeWithAny.ts, 43, 1)) +>abc : Symbol(abc, Decl(mappedTypeWithAny.ts, 49, 3)) +>stringifyArray : Symbol(stringifyArray, Decl(mappedTypeWithAny.ts, 46, 1)) diff --git a/tests/baselines/reference/mappedTypeWithAny.types b/tests/baselines/reference/mappedTypeWithAny.types index f36d357325e12..f60dd9357fb18 100644 --- a/tests/baselines/reference/mappedTypeWithAny.types +++ b/tests/baselines/reference/mappedTypeWithAny.types @@ -68,8 +68,11 @@ type Objectish = { [K in keyof T]: T[K] }; // When a mapped type whose constraint is `keyof T` is instantiated, // `T` may be instantiated with a `U` which is constrained to -// array and tuple types. When `U` is later instantiated with `any`, -// the result should also be some sort of array. +// array and tuple types. *Ideally*, when `U` is later instantiated with `any`, +// the result should also be some sort of array; however, at the moment we don't seem +// to have an easy way to preserve that information. More than just that, it would be +// inconsistent for two instantiations of `Objectish` to produce different outputs +// depending on the usage-site. As a result, `IndirectArrayish` does not act like `Arrayish`. type IndirectArrayish = Objectish; >IndirectArrayish : Objectish From d1939aa21acaf58991b6d44312cbf53bfe149de3 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 22 Oct 2021 22:36:30 +0000 Subject: [PATCH 12/17] Added tuple test case. --- tests/cases/conformance/types/mapped/mappedTypeWithAny.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts index 1140bc35c0c79..41eaa5945c91c 100644 --- a/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts +++ b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts @@ -50,4 +50,7 @@ function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayis } declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; -let abc: any[] = stringifyArray(void 0 as any); \ No newline at end of file +let abc: any[] = stringifyArray(void 0 as any); + +declare function stringifyPair(arr: T): { -readonly [K in keyof T]: string }; +let def: [any, any] = stringifyPair(void 0 as any); \ No newline at end of file From de7f98cf6930de15fa91e4345864ae5dff78127e Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 22 Oct 2021 22:38:19 +0000 Subject: [PATCH 13/17] Accepted baselines. --- .../baselines/reference/mappedTypeWithAny.errors.txt | 12 ++++++++++-- tests/baselines/reference/mappedTypeWithAny.js | 10 +++++++++- tests/baselines/reference/mappedTypeWithAny.symbols | 12 ++++++++++++ tests/baselines/reference/mappedTypeWithAny.types | 12 ++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/mappedTypeWithAny.errors.txt b/tests/baselines/reference/mappedTypeWithAny.errors.txt index f611472caed7c..77a1e3e81a167 100644 --- a/tests/baselines/reference/mappedTypeWithAny.errors.txt +++ b/tests/baselines/reference/mappedTypeWithAny.errors.txt @@ -1,9 +1,11 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(23,16): error TS2339: Property 'notAValue' does not exist on type 'Data'. tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(45,5): error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(46,5): error TS2322: Type 'Objectish' is not assignable to type 'any[]'. +tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(53,5): error TS2322: Type 'string[]' is not assignable to type '[any, any]'. + Target requires 2 element(s) but source may have fewer. -==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (3 errors) ==== +==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (4 errors) ==== type Item = { value: string }; type ItemMap = { [P in keyof T]: Item }; @@ -59,4 +61,10 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(46,5): error TS2322: T } declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; - let abc: any[] = stringifyArray(void 0 as any); \ No newline at end of file + let abc: any[] = stringifyArray(void 0 as any); + + declare function stringifyPair(arr: T): { -readonly [K in keyof T]: string }; + let def: [any, any] = stringifyPair(void 0 as any); + ~~~ +!!! error TS2322: Type 'string[]' is not assignable to type '[any, any]'. +!!! error TS2322: Target requires 2 element(s) but source may have fewer. \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAny.js b/tests/baselines/reference/mappedTypeWithAny.js index 0a683792784c8..a36e8fa3cd917 100644 --- a/tests/baselines/reference/mappedTypeWithAny.js +++ b/tests/baselines/reference/mappedTypeWithAny.js @@ -48,7 +48,10 @@ function bar(arrayish: Arrayish, objectish: Objectish, indirectArrayis } declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string }; -let abc: any[] = stringifyArray(void 0 as any); +let abc: any[] = stringifyArray(void 0 as any); + +declare function stringifyPair(arr: T): { -readonly [K in keyof T]: string }; +let def: [any, any] = stringifyPair(void 0 as any); //// [mappedTypeWithAny.js] "use strict"; @@ -63,6 +66,7 @@ function bar(arrayish, objectish, indirectArrayish) { arr = indirectArrayish; } var abc = stringifyArray(void 0); +var def = stringifyPair(void 0); //// [mappedTypeWithAny.d.ts] @@ -102,3 +106,7 @@ declare function stringifyArray(arr: T): { -readonly [K in keyof T]: string; }; declare let abc: any[]; +declare function stringifyPair(arr: T): { + -readonly [K in keyof T]: string; +}; +declare let def: [any, any]; diff --git a/tests/baselines/reference/mappedTypeWithAny.symbols b/tests/baselines/reference/mappedTypeWithAny.symbols index 0c4c95f444050..6b411af1f4529 100644 --- a/tests/baselines/reference/mappedTypeWithAny.symbols +++ b/tests/baselines/reference/mappedTypeWithAny.symbols @@ -139,3 +139,15 @@ let abc: any[] = stringifyArray(void 0 as any); >abc : Symbol(abc, Decl(mappedTypeWithAny.ts, 49, 3)) >stringifyArray : Symbol(stringifyArray, Decl(mappedTypeWithAny.ts, 46, 1)) +declare function stringifyPair(arr: T): { -readonly [K in keyof T]: string }; +>stringifyPair : Symbol(stringifyPair, Decl(mappedTypeWithAny.ts, 49, 47)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 51, 31)) +>arr : Symbol(arr, Decl(mappedTypeWithAny.ts, 51, 62)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 51, 31)) +>K : Symbol(K, Decl(mappedTypeWithAny.ts, 51, 84)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 51, 31)) + +let def: [any, any] = stringifyPair(void 0 as any); +>def : Symbol(def, Decl(mappedTypeWithAny.ts, 52, 3)) +>stringifyPair : Symbol(stringifyPair, Decl(mappedTypeWithAny.ts, 49, 47)) + diff --git a/tests/baselines/reference/mappedTypeWithAny.types b/tests/baselines/reference/mappedTypeWithAny.types index f60dd9357fb18..f8eb3abf08708 100644 --- a/tests/baselines/reference/mappedTypeWithAny.types +++ b/tests/baselines/reference/mappedTypeWithAny.types @@ -113,3 +113,15 @@ let abc: any[] = stringifyArray(void 0 as any); >void 0 : undefined >0 : 0 +declare function stringifyPair(arr: T): { -readonly [K in keyof T]: string }; +>stringifyPair : (arr: T) => { -readonly [K in keyof T]: string; } +>arr : T + +let def: [any, any] = stringifyPair(void 0 as any); +>def : [any, any] +>stringifyPair(void 0 as any) : string[] +>stringifyPair : (arr: T) => { -readonly [K in keyof T]: string; } +>void 0 as any : any +>void 0 : undefined +>0 : 0 + From f01ae16e6589ec42a931b018ffea03453df60e35 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 22 Oct 2021 22:39:28 +0000 Subject: [PATCH 14/17] Don't add special behavior for tuples. --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 043745c7c5c28..f062997364bdd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16516,7 +16516,7 @@ namespace ts { if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t)) { if (!type.declaration.nameType) { let constraint; - if (isArrayType(t) || (t.flags & TypeFlags.Any) && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, or(isArrayType, isTupleType))) { + if (isArrayType(t) || (t.flags & TypeFlags.Any) && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayType)) { return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); } if (isGenericTupleType(t)) { From f342c82fde314225994238ee9d5f950410eb0462 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 22 Oct 2021 22:40:08 +0000 Subject: [PATCH 15/17] Accepted baselines. --- tests/baselines/reference/mappedTypeWithAny.errors.txt | 6 ++---- tests/baselines/reference/mappedTypeWithAny.types | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/baselines/reference/mappedTypeWithAny.errors.txt b/tests/baselines/reference/mappedTypeWithAny.errors.txt index 77a1e3e81a167..e7057de0ff16e 100644 --- a/tests/baselines/reference/mappedTypeWithAny.errors.txt +++ b/tests/baselines/reference/mappedTypeWithAny.errors.txt @@ -1,8 +1,7 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(23,16): error TS2339: Property 'notAValue' does not exist on type 'Data'. tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(45,5): error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(46,5): error TS2322: Type 'Objectish' is not assignable to type 'any[]'. -tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(53,5): error TS2322: Type 'string[]' is not assignable to type '[any, any]'. - Target requires 2 element(s) but source may have fewer. +tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(53,5): error TS2322: Type '{ [x: string]: string; }' is not assignable to type '[any, any]'. ==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (4 errors) ==== @@ -66,5 +65,4 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(53,5): error TS2322: T declare function stringifyPair(arr: T): { -readonly [K in keyof T]: string }; let def: [any, any] = stringifyPair(void 0 as any); ~~~ -!!! error TS2322: Type 'string[]' is not assignable to type '[any, any]'. -!!! error TS2322: Target requires 2 element(s) but source may have fewer. \ No newline at end of file +!!! error TS2322: Type '{ [x: string]: string; }' is not assignable to type '[any, any]'. \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAny.types b/tests/baselines/reference/mappedTypeWithAny.types index f8eb3abf08708..4b6610d678e53 100644 --- a/tests/baselines/reference/mappedTypeWithAny.types +++ b/tests/baselines/reference/mappedTypeWithAny.types @@ -119,7 +119,7 @@ declare function stringifyPair(arr: T): { -readon let def: [any, any] = stringifyPair(void 0 as any); >def : [any, any] ->stringifyPair(void 0 as any) : string[] +>stringifyPair(void 0 as any) : { [x: string]: string; } >stringifyPair : (arr: T) => { -readonly [K in keyof T]: string; } >void 0 as any : any >void 0 : undefined From 46283e249a25b1ce45cfc2b5f529a2d343def31d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 27 Oct 2021 12:16:38 +0000 Subject: [PATCH 16/17] Revert "Don't add special behavior for tuples." This reverts commit f01ae16e6589ec42a931b018ffea03453df60e35. --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f062997364bdd..043745c7c5c28 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16516,7 +16516,7 @@ namespace ts { if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t)) { if (!type.declaration.nameType) { let constraint; - if (isArrayType(t) || (t.flags & TypeFlags.Any) && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayType)) { + if (isArrayType(t) || (t.flags & TypeFlags.Any) && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, or(isArrayType, isTupleType))) { return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); } if (isGenericTupleType(t)) { From b3492a923161dfcce16cb6a5ec913fb174df356d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 27 Oct 2021 12:21:10 +0000 Subject: [PATCH 17/17] Accepted baselines. --- tests/baselines/reference/mappedTypeWithAny.errors.txt | 6 ++++-- tests/baselines/reference/mappedTypeWithAny.types | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/mappedTypeWithAny.errors.txt b/tests/baselines/reference/mappedTypeWithAny.errors.txt index e7057de0ff16e..77a1e3e81a167 100644 --- a/tests/baselines/reference/mappedTypeWithAny.errors.txt +++ b/tests/baselines/reference/mappedTypeWithAny.errors.txt @@ -1,7 +1,8 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(23,16): error TS2339: Property 'notAValue' does not exist on type 'Data'. tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(45,5): error TS2740: Type 'Objectish' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more. tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(46,5): error TS2322: Type 'Objectish' is not assignable to type 'any[]'. -tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(53,5): error TS2322: Type '{ [x: string]: string; }' is not assignable to type '[any, any]'. +tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(53,5): error TS2322: Type 'string[]' is not assignable to type '[any, any]'. + Target requires 2 element(s) but source may have fewer. ==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (4 errors) ==== @@ -65,4 +66,5 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(53,5): error TS2322: T declare function stringifyPair(arr: T): { -readonly [K in keyof T]: string }; let def: [any, any] = stringifyPair(void 0 as any); ~~~ -!!! error TS2322: Type '{ [x: string]: string; }' is not assignable to type '[any, any]'. \ No newline at end of file +!!! error TS2322: Type 'string[]' is not assignable to type '[any, any]'. +!!! error TS2322: Target requires 2 element(s) but source may have fewer. \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAny.types b/tests/baselines/reference/mappedTypeWithAny.types index 4b6610d678e53..f8eb3abf08708 100644 --- a/tests/baselines/reference/mappedTypeWithAny.types +++ b/tests/baselines/reference/mappedTypeWithAny.types @@ -119,7 +119,7 @@ declare function stringifyPair(arr: T): { -readon let def: [any, any] = stringifyPair(void 0 as any); >def : [any, any] ->stringifyPair(void 0 as any) : { [x: string]: string; } +>stringifyPair(void 0 as any) : string[] >stringifyPair : (arr: T) => { -readonly [K in keyof T]: string; } >void 0 as any : any >void 0 : undefined