From 68585f2a1e964bc9a8dccf9c7a6bb6c82498b6c6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 17 Apr 2019 11:20:50 -0700 Subject: [PATCH 01/33] Ignore string (but keep numeric) index signatures coming from constraints --- src/compiler/checker.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0c91e1ba06208..0a025f29c20c4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9864,13 +9864,13 @@ namespace ts { return type.flags & TypeFlags.Union ? getIntersectionType(map((type).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) : type.flags & TypeFlags.Intersection ? getUnionType(map((type).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) : maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive) ? getIndexTypeForGenericType(type, stringsOnly) : - getObjectFlags(type) & ObjectFlags.Mapped ? filterType(getConstraintTypeFromMappedType(type), t => !(noIndexSignatures && t.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number))) : + getObjectFlags(type) & ObjectFlags.Mapped ? filterType(getConstraintTypeFromMappedType(type), t => !(noIndexSignatures && t.flags & (TypeFlags.Any | TypeFlags.String))) : type === wildcardType ? wildcardType : type.flags & TypeFlags.Unknown ? neverType : type.flags & (TypeFlags.Any | TypeFlags.Never) ? keyofConstraintType : stringsOnly ? !noIndexSignatures && getIndexInfoOfType(type, IndexKind.String) ? stringType : getLiteralTypeFromProperties(type, TypeFlags.StringLiteral) : !noIndexSignatures && getIndexInfoOfType(type, IndexKind.String) ? getUnionType([stringType, numberType, getLiteralTypeFromProperties(type, TypeFlags.UniqueESSymbol)]) : - !noIndexSignatures && getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromProperties(type, TypeFlags.StringLiteral | TypeFlags.UniqueESSymbol)]) : + getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromProperties(type, TypeFlags.StringLiteral | TypeFlags.UniqueESSymbol)]) : getLiteralTypeFromProperties(type, TypeFlags.StringOrNumberLiteralOrUnique); } @@ -9988,10 +9988,10 @@ namespace ts { if (objectType.flags & (TypeFlags.Any | TypeFlags.Never)) { return objectType; } - const indexInfo = isTypeAssignableToKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) || - getIndexInfoOfType(objectType, IndexKind.String); + const stringIndexInfo = getIndexInfoOfType(objectType, IndexKind.String); + const indexInfo = isTypeAssignableToKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) || stringIndexInfo; if (indexInfo) { - if (accessFlags & AccessFlags.NoIndexSignatures) { + if (accessFlags & AccessFlags.NoIndexSignatures && indexInfo === stringIndexInfo) { if (accessExpression) { error(accessExpression, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(originalObjectType)); } From 07d259593a78815b8fdc00c6c2db4f5ffa602cfb Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 17 Apr 2019 12:37:01 -0700 Subject: [PATCH 02/33] Add regression test --- .../conformance/types/keyof/keyofAndIndexedAccess2.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts index 2d96e20f12a9d..2d63e5681bab6 100644 --- a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts @@ -110,3 +110,13 @@ interface Type { function get123(): Type[K] { return 123; // Error } + +// Repros from #30938 + +function fn} | {elements: Array}>(param: T, cb: (element: T['elements'][number]) => void) { + cb(param.elements[0]); +} + +function fn2>(param: T, cb: (element: T[number]) => void) { + cb(param[0]); +} From f9a55ac55ec1b99e4f2a835040bce1441aefc9a0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 17 Apr 2019 12:37:10 -0700 Subject: [PATCH 03/33] Accept new baselines --- .../keyofAndIndexedAccess2.errors.txt | 10 +++++ .../reference/keyofAndIndexedAccess2.js | 17 +++++++++ .../reference/keyofAndIndexedAccess2.symbols | 37 +++++++++++++++++++ .../reference/keyofAndIndexedAccess2.types | 34 +++++++++++++++++ 4 files changed, 98 insertions(+) diff --git a/tests/baselines/reference/keyofAndIndexedAccess2.errors.txt b/tests/baselines/reference/keyofAndIndexedAccess2.errors.txt index 6e1b87a72e38d..ba2fe38c1451b 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess2.errors.txt +++ b/tests/baselines/reference/keyofAndIndexedAccess2.errors.txt @@ -187,4 +187,14 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts(108,5): error TS23 !!! error TS2322: Type '123' is not assignable to type '123 & "some string"'. !!! error TS2322: Type '123' is not assignable to type '"some string"'. } + + // Repros from #30938 + + function fn} | {elements: Array}>(param: T, cb: (element: T['elements'][number]) => void) { + cb(param.elements[0]); + } + + function fn2>(param: T, cb: (element: T[number]) => void) { + cb(param[0]); + } \ No newline at end of file diff --git a/tests/baselines/reference/keyofAndIndexedAccess2.js b/tests/baselines/reference/keyofAndIndexedAccess2.js index 8dad708c2988c..2ef82b3d68efd 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess2.js +++ b/tests/baselines/reference/keyofAndIndexedAccess2.js @@ -108,6 +108,16 @@ interface Type { function get123(): Type[K] { return 123; // Error } + +// Repros from #30938 + +function fn} | {elements: Array}>(param: T, cb: (element: T['elements'][number]) => void) { + cb(param.elements[0]); +} + +function fn2>(param: T, cb: (element: T[number]) => void) { + cb(param[0]); +} //// [keyofAndIndexedAccess2.js] @@ -183,3 +193,10 @@ export function getEntity(id, state) { function get123() { return 123; // Error } +// Repros from #30938 +function fn(param, cb) { + cb(param.elements[0]); +} +function fn2(param, cb) { + cb(param[0]); +} diff --git a/tests/baselines/reference/keyofAndIndexedAccess2.symbols b/tests/baselines/reference/keyofAndIndexedAccess2.symbols index 803700efa372a..5113eb736db5d 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess2.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccess2.symbols @@ -388,3 +388,40 @@ function get123(): Type[K] { return 123; // Error } +// Repros from #30938 + +function fn} | {elements: Array}>(param: T, cb: (element: T['elements'][number]) => void) { +>fn : Symbol(fn, Decl(keyofAndIndexedAccess2.ts, 108, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 112, 12)) +>elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 112, 23)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) +>elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 112, 51)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) +>param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 112, 77)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 112, 12)) +>cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 112, 86)) +>element : Symbol(element, Decl(keyofAndIndexedAccess2.ts, 112, 92)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 112, 12)) + + cb(param.elements[0]); +>cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 112, 86)) +>param.elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 112, 23), Decl(keyofAndIndexedAccess2.ts, 112, 51)) +>param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 112, 77)) +>elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 112, 23), Decl(keyofAndIndexedAccess2.ts, 112, 51)) +} + +function fn2>(param: T, cb: (element: T[number]) => void) { +>fn2 : Symbol(fn2, Decl(keyofAndIndexedAccess2.ts, 114, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 116, 13)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) +>param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 116, 38)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 116, 13)) +>cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 116, 47)) +>element : Symbol(element, Decl(keyofAndIndexedAccess2.ts, 116, 53)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 116, 13)) + + cb(param[0]); +>cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 116, 47)) +>param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 116, 38)) +} + diff --git a/tests/baselines/reference/keyofAndIndexedAccess2.types b/tests/baselines/reference/keyofAndIndexedAccess2.types index 5f5b80a481911..286db62e4b565 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess2.types +++ b/tests/baselines/reference/keyofAndIndexedAccess2.types @@ -423,3 +423,37 @@ function get123(): Type[K] { >123 : 123 } +// Repros from #30938 + +function fn} | {elements: Array}>(param: T, cb: (element: T['elements'][number]) => void) { +>fn : (param: T, cb: (element: T["elements"][number]) => void) => void +>elements : string[] +>elements : number[] +>param : T +>cb : (element: T["elements"][number]) => void +>element : T["elements"][number] + + cb(param.elements[0]); +>cb(param.elements[0]) : void +>cb : (element: T["elements"][number]) => void +>param.elements[0] : string | number +>param.elements : string[] | number[] +>param : T +>elements : string[] | number[] +>0 : 0 +} + +function fn2>(param: T, cb: (element: T[number]) => void) { +>fn2 : (param: T, cb: (element: T[number]) => void) => void +>param : T +>cb : (element: T[number]) => void +>element : T[number] + + cb(param[0]); +>cb(param[0]) : void +>cb : (element: T[number]) => void +>param[0] : string +>param : T +>0 : 0 +} + From 4ce0d202e9eab846e6c60eda3cc8c39adc001415 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 18 Apr 2019 11:39:36 -0700 Subject: [PATCH 04/33] Accept new baselines --- .../keyofAndIndexedAccess2.errors.txt | 16 ++-- .../reference/keyofAndIndexedAccess2.js | 16 ++-- .../reference/keyofAndIndexedAccess2.symbols | 76 +++++++++---------- .../reference/keyofAndIndexedAccess2.types | 30 ++++---- 4 files changed, 65 insertions(+), 73 deletions(-) diff --git a/tests/baselines/reference/keyofAndIndexedAccess2.errors.txt b/tests/baselines/reference/keyofAndIndexedAccess2.errors.txt index 8b018263a4b1e..9a937066374ab 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess2.errors.txt +++ b/tests/baselines/reference/keyofAndIndexedAccess2.errors.txt @@ -188,7 +188,13 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts(108,5): error TS23 !!! error TS2322: Type '123' is not assignable to type '"some string"'. } -<<<<<<< HEAD + // Repro from #30920 + + type StrictExtract = T extends U ? U extends T ? T : never : never; + type StrictExclude = T extends StrictExtract ? never : T; + type A = { [Q in { [P in keyof T]: P; }[keyof T]]: T[Q]; }; + type B = A<{ [Q in keyof T]: StrictExclude, {}>; }>; + // Repros from #30938 function fn} | {elements: Array}>(param: T, cb: (element: T['elements'][number]) => void) { @@ -198,12 +204,4 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccess2.ts(108,5): error TS23 function fn2>(param: T, cb: (element: T[number]) => void) { cb(param[0]); } -======= - // Repro from #30920 - - type StrictExtract = T extends U ? U extends T ? T : never : never; - type StrictExclude = T extends StrictExtract ? never : T; - type A = { [Q in { [P in keyof T]: P; }[keyof T]]: T[Q]; }; - type B = A<{ [Q in keyof T]: StrictExclude, {}>; }>; ->>>>>>> master \ No newline at end of file diff --git a/tests/baselines/reference/keyofAndIndexedAccess2.js b/tests/baselines/reference/keyofAndIndexedAccess2.js index 9956a17bf4748..906bcd0eab3de 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess2.js +++ b/tests/baselines/reference/keyofAndIndexedAccess2.js @@ -109,7 +109,13 @@ function get123(): Type[K] { return 123; // Error } -<<<<<<< HEAD +// Repro from #30920 + +type StrictExtract = T extends U ? U extends T ? T : never : never; +type StrictExclude = T extends StrictExtract ? never : T; +type A = { [Q in { [P in keyof T]: P; }[keyof T]]: T[Q]; }; +type B = A<{ [Q in keyof T]: StrictExclude, {}>; }>; + // Repros from #30938 function fn} | {elements: Array}>(param: T, cb: (element: T['elements'][number]) => void) { @@ -119,14 +125,6 @@ function fn} | {elements: Array}>(par function fn2>(param: T, cb: (element: T[number]) => void) { cb(param[0]); } -======= -// Repro from #30920 - -type StrictExtract = T extends U ? U extends T ? T : never : never; -type StrictExclude = T extends StrictExtract ? never : T; -type A = { [Q in { [P in keyof T]: P; }[keyof T]]: T[Q]; }; -type B = A<{ [Q in keyof T]: StrictExclude, {}>; }>; ->>>>>>> master //// [keyofAndIndexedAccess2.js] diff --git a/tests/baselines/reference/keyofAndIndexedAccess2.symbols b/tests/baselines/reference/keyofAndIndexedAccess2.symbols index e0eb723649a4c..24e1a8b0674e7 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess2.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccess2.symbols @@ -388,44 +388,6 @@ function get123(): Type[K] { return 123; // Error } -<<<<<<< HEAD -// Repros from #30938 - -function fn} | {elements: Array}>(param: T, cb: (element: T['elements'][number]) => void) { ->fn : Symbol(fn, Decl(keyofAndIndexedAccess2.ts, 108, 1)) ->T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 112, 12)) ->elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 112, 23)) ->Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) ->elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 112, 51)) ->Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) ->param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 112, 77)) ->T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 112, 12)) ->cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 112, 86)) ->element : Symbol(element, Decl(keyofAndIndexedAccess2.ts, 112, 92)) ->T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 112, 12)) - - cb(param.elements[0]); ->cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 112, 86)) ->param.elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 112, 23), Decl(keyofAndIndexedAccess2.ts, 112, 51)) ->param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 112, 77)) ->elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 112, 23), Decl(keyofAndIndexedAccess2.ts, 112, 51)) -} - -function fn2>(param: T, cb: (element: T[number]) => void) { ->fn2 : Symbol(fn2, Decl(keyofAndIndexedAccess2.ts, 114, 1)) ->T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 116, 13)) ->Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) ->param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 116, 38)) ->T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 116, 13)) ->cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 116, 47)) ->element : Symbol(element, Decl(keyofAndIndexedAccess2.ts, 116, 53)) ->T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 116, 13)) - - cb(param[0]); ->cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 116, 47)) ->param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 116, 38)) -} -======= // Repro from #30920 type StrictExtract = T extends U ? U extends T ? T : never : never; @@ -471,5 +433,41 @@ type B = A<{ [Q in keyof T]: StrictExclude, {}>; }>; >T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 115, 7)) >Q : Symbol(Q, Decl(keyofAndIndexedAccess2.ts, 115, 20)) >V : Symbol(V, Decl(keyofAndIndexedAccess2.ts, 115, 9)) ->>>>>>> master + +// Repros from #30938 + +function fn} | {elements: Array}>(param: T, cb: (element: T['elements'][number]) => void) { +>fn : Symbol(fn, Decl(keyofAndIndexedAccess2.ts, 115, 69)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 119, 12)) +>elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 119, 23)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) +>elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 119, 51)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) +>param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 119, 77)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 119, 12)) +>cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 119, 86)) +>element : Symbol(element, Decl(keyofAndIndexedAccess2.ts, 119, 92)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 119, 12)) + + cb(param.elements[0]); +>cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 119, 86)) +>param.elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 119, 23), Decl(keyofAndIndexedAccess2.ts, 119, 51)) +>param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 119, 77)) +>elements : Symbol(elements, Decl(keyofAndIndexedAccess2.ts, 119, 23), Decl(keyofAndIndexedAccess2.ts, 119, 51)) +} + +function fn2>(param: T, cb: (element: T[number]) => void) { +>fn2 : Symbol(fn2, Decl(keyofAndIndexedAccess2.ts, 121, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 123, 13)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) +>param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 123, 38)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 123, 13)) +>cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 123, 47)) +>element : Symbol(element, Decl(keyofAndIndexedAccess2.ts, 123, 53)) +>T : Symbol(T, Decl(keyofAndIndexedAccess2.ts, 123, 13)) + + cb(param[0]); +>cb : Symbol(cb, Decl(keyofAndIndexedAccess2.ts, 123, 47)) +>param : Symbol(param, Decl(keyofAndIndexedAccess2.ts, 123, 38)) +} diff --git a/tests/baselines/reference/keyofAndIndexedAccess2.types b/tests/baselines/reference/keyofAndIndexedAccess2.types index 16bd970d341c8..6c0f3dff934d8 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess2.types +++ b/tests/baselines/reference/keyofAndIndexedAccess2.types @@ -423,7 +423,20 @@ function get123(): Type[K] { >123 : 123 } -<<<<<<< HEAD +// Repro from #30920 + +type StrictExtract = T extends U ? U extends T ? T : never : never; +>StrictExtract : StrictExtract + +type StrictExclude = T extends StrictExtract ? never : T; +>StrictExclude : StrictExclude + +type A = { [Q in { [P in keyof T]: P; }[keyof T]]: T[Q]; }; +>A : A + +type B = A<{ [Q in keyof T]: StrictExclude, {}>; }>; +>B : A<{ [Q in keyof T]: StrictExclude, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }> + // Repros from #30938 function fn} | {elements: Array}>(param: T, cb: (element: T['elements'][number]) => void) { @@ -457,19 +470,4 @@ function fn2>(param: T, cb: (element: T[number]) => void >param : T >0 : 0 } -======= -// Repro from #30920 - -type StrictExtract = T extends U ? U extends T ? T : never : never; ->StrictExtract : StrictExtract - -type StrictExclude = T extends StrictExtract ? never : T; ->StrictExclude : StrictExclude - -type A = { [Q in { [P in keyof T]: P; }[keyof T]]: T[Q]; }; ->A : A - -type B = A<{ [Q in keyof T]: StrictExclude, {}>; }>; ->B : A<{ [Q in keyof T]: StrictExclude, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }>, {}>; }> ->>>>>>> master From fc7b7c83b339998e972522541b18464506e179f4 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Wed, 24 Apr 2019 10:41:17 -0700 Subject: [PATCH 05/33] Exclude tests/cases from tslint --- tslint.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tslint.json b/tslint.json index 5952c770c5e7e..c43f84b69aecd 100644 --- a/tslint.json +++ b/tslint.json @@ -1,6 +1,11 @@ { "extends": "tslint:latest", "rulesDirectory": "built/local/tslint/rules", + "linterOptions": { + "exclude": [ + "tests/cases/**/*" + ] + }, "rules": { "no-unnecessary-type-assertion": true, From 7ba1c8aba2e2c7b047d077f8c75c7f7f5c0207fc Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Wed, 24 Apr 2019 11:35:37 -0700 Subject: [PATCH 06/33] Exclude everything in tests --- tslint.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tslint.json b/tslint.json index c43f84b69aecd..5b75ed1a55b74 100644 --- a/tslint.json +++ b/tslint.json @@ -3,7 +3,7 @@ "rulesDirectory": "built/local/tslint/rules", "linterOptions": { "exclude": [ - "tests/cases/**/*" + "tests/**/*" ] }, "rules": { From 3264b64f08cd3a946fecf9b9ebd9d741190b5543 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 23 Apr 2019 15:32:02 -0700 Subject: [PATCH 07/33] Reuse map if module resolution is same for redirected and own files --- src/compiler/moduleNameResolver.ts | 11 ++++++----- src/compiler/program.ts | 2 +- src/compiler/utilities.ts | 7 ++++++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index b8aa9fa2df465..090abfa978e7d 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -436,10 +436,10 @@ namespace ts { set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; } - export function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache { + export function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions): ModuleResolutionCache { return createModuleResolutionCacheWithMaps( - createCacheWithRedirects(), - createCacheWithRedirects(), + createCacheWithRedirects(options), + createCacheWithRedirects(options), currentDirectory, getCanonicalFileName ); @@ -454,7 +454,7 @@ namespace ts { } /*@internal*/ - export function createCacheWithRedirects(): CacheWithRedirects { + export function createCacheWithRedirects(options?: CompilerOptions): CacheWithRedirects { const ownMap: Map = createMap(); const redirectsMap: Map> = createMap(); return { @@ -471,7 +471,8 @@ namespace ts { const path = redirectedReference.sourceFile.path; let redirects = redirectsMap.get(path); if (!redirects) { - redirects = createMap(); + // Reuse map if redirected reference map uses same resolution + redirects = !options || optionsHaveModuleResolutionChanges(options, redirectedReference.commandLine.options) ? createMap() : ownMap; redirectsMap.set(path, redirects); } return redirects; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 4f50aa3ab1f59..c6c592b0e7381 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -773,7 +773,7 @@ namespace ts { }); } else { - moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host.getCanonicalFileName(x)); + moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host.getCanonicalFileName(x), options); const loader = (moduleName: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache, redirectedReference).resolvedModule!; // TODO: GH#18217 resolveModuleNamesWorker = (moduleNames, containingFile, _reusedNames, redirectedReference) => loadWithLocalCache(Debug.assertEachDefined(moduleNames), containingFile, redirectedReference, loader); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 2e6c3ae4f866e..5e7474920fd27 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -101,7 +101,12 @@ namespace ts { } export function changesAffectModuleResolution(oldOptions: CompilerOptions, newOptions: CompilerOptions): boolean { - return oldOptions.configFilePath !== newOptions.configFilePath || moduleResolutionOptionDeclarations.some(o => + return oldOptions.configFilePath !== newOptions.configFilePath || + optionsHaveModuleResolutionChanges(oldOptions, newOptions); + } + + export function optionsHaveModuleResolutionChanges(oldOptions: CompilerOptions, newOptions: CompilerOptions) { + return moduleResolutionOptionDeclarations.some(o => !isJsonEqual(getCompilerOptionValue(oldOptions, o), getCompilerOptionValue(newOptions, o))); } From 93b958e0ea1f61565802fa47df75176e4b38aa47 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 24 Apr 2019 12:38:25 -0700 Subject: [PATCH 08/33] Share module resolution cache among different program --- src/compiler/moduleNameResolver.ts | 21 ++++++++++++++--- src/compiler/program.ts | 3 ++- src/compiler/tsbuild.ts | 37 ++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 090abfa978e7d..c8b32fa6010d2 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -421,6 +421,7 @@ namespace ts { */ export interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache { getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): Map; + /*@internal*/ directoryToModuleNameMap: CacheWithRedirects>; } /** @@ -429,6 +430,7 @@ namespace ts { */ export interface NonRelativeModuleNameResolutionCache { getOrCreateCacheForModuleName(nonRelativeModuleName: string, redirectedReference?: ResolvedProjectReference): PerModuleNameCache; + /*@internal*/ moduleNameToDirectoryMap: CacheWithRedirects; } export interface PerModuleNameCache { @@ -445,25 +447,38 @@ namespace ts { ); } + /*@internal*/ export interface CacheWithRedirects { ownMap: Map; redirectsMap: Map>; getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): Map; clear(): void; + setOwnOptions(newOptions: CompilerOptions): void; + setOwnMap(newOwnMap: Map): void; } /*@internal*/ export function createCacheWithRedirects(options?: CompilerOptions): CacheWithRedirects { - const ownMap: Map = createMap(); + let ownMap: Map = createMap(); const redirectsMap: Map> = createMap(); return { ownMap, redirectsMap, getOrCreateMapOfCacheRedirects, - clear + clear, + setOwnOptions, + setOwnMap }; + function setOwnOptions(newOptions: CompilerOptions) { + options = newOptions; + } + + function setOwnMap(newOwnMap: Map) { + ownMap = newOwnMap; + } + function getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined) { if (!redirectedReference) { return ownMap; @@ -491,7 +506,7 @@ namespace ts { currentDirectory: string, getCanonicalFileName: GetCanonicalFileName): ModuleResolutionCache { - return { getOrCreateCacheForDirectory, getOrCreateCacheForModuleName }; + return { getOrCreateCacheForDirectory, getOrCreateCacheForModuleName, directoryToModuleNameMap, moduleNameToDirectoryMap }; function getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference) { const path = toPath(directoryName, currentDirectory, getCanonicalFileName); diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c6c592b0e7381..e8b2ba39b13a7 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -528,7 +528,8 @@ namespace ts { } } - function loadWithLocalCache(names: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, loader: (name: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => T): T[] { + /* @internal */ + export function loadWithLocalCache(names: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, loader: (name: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => T): T[] { if (names.length === 0) { return []; } diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index f60641fe0cfe7..8bc66e95edc45 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -400,6 +400,10 @@ namespace ts { const compilerHost = createCompilerHostFromProgramHost(host, () => projectCompilerOptions); setGetSourceFileAsHashVersioned(compilerHost, host); + compilerHost.resolveModuleNames = maybeBind(host, host.resolveModuleNames); + compilerHost.resolveTypeReferenceDirectives = maybeBind(host, host.resolveTypeReferenceDirectives); + let moduleResolutionCache = !compilerHost.resolveModuleNames ? createModuleResolutionCache(currentDirectory, getCanonicalFileName) : undefined; + const buildInfoChecked = createFileMap(toPath); // Watch state @@ -1097,6 +1101,30 @@ namespace ts { // TODO: handle resolve module name to cache result in project reference redirect projectCompilerOptions = configFile.options; + // Update module resolution cache if needed + if (moduleResolutionCache) { + const projPath = toPath(proj); + if (moduleResolutionCache.directoryToModuleNameMap.redirectsMap.size === 0) { + // The own map will be for projectCompilerOptions + Debug.assert(moduleResolutionCache.moduleNameToDirectoryMap.redirectsMap.size === 0); + moduleResolutionCache.directoryToModuleNameMap.redirectsMap.set(projPath, moduleResolutionCache.directoryToModuleNameMap.ownMap); + moduleResolutionCache.moduleNameToDirectoryMap.redirectsMap.set(projPath, moduleResolutionCache.moduleNameToDirectoryMap.ownMap); + } + else { + // Set correct own map + Debug.assert(moduleResolutionCache.moduleNameToDirectoryMap.redirectsMap.size > 0); + + const ref: ResolvedProjectReference = { + sourceFile: projectCompilerOptions.configFile!, + commandLine: configFile + }; + moduleResolutionCache.directoryToModuleNameMap.setOwnMap(moduleResolutionCache.directoryToModuleNameMap.getOrCreateMapOfCacheRedirects(ref)); + moduleResolutionCache.moduleNameToDirectoryMap.setOwnMap(moduleResolutionCache.moduleNameToDirectoryMap.getOrCreateMapOfCacheRedirects(ref)); + } + moduleResolutionCache.directoryToModuleNameMap.setOwnOptions(projectCompilerOptions); + moduleResolutionCache.moduleNameToDirectoryMap.setOwnOptions(projectCompilerOptions); + } + const program = host.createProgram( configFile.fileNames, configFile.options, @@ -1368,6 +1396,13 @@ namespace ts { readFileWithCache = newReadFileWithCache; compilerHost.getSourceFile = getSourceFileWithCache!; + const originalResolveModuleNames = compilerHost.resolveModuleNames; + if (!compilerHost.resolveModuleNames) { + const loader = (moduleName: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveModuleName(moduleName, containingFile, projectCompilerOptions, compilerHost, moduleResolutionCache, redirectedReference).resolvedModule!; + compilerHost.resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference) => + loadWithLocalCache(Debug.assertEachDefined(moduleNames), containingFile, redirectedReference, loader); + } + const graph = getGlobalDependencyGraph(); reportBuildQueue(graph); let anyFailed = false; @@ -1428,6 +1463,8 @@ namespace ts { host.writeFile = originalWriteFile; compilerHost.getSourceFile = savedGetSourceFile; readFileWithCache = savedReadFileWithCache; + compilerHost.resolveModuleNames = originalResolveModuleNames; + moduleResolutionCache = undefined; return anyFailed ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success; } From 60e7b5d17e9fc7ebfc7c55154cc000db0d773721 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 24 Apr 2019 16:43:17 -0700 Subject: [PATCH 09/33] Added tests. --- tests/cases/compiler/omitTypeTestErrors01.ts | 19 +++++++++++++++++++ tests/cases/compiler/omitTypeTests01.ts | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 tests/cases/compiler/omitTypeTestErrors01.ts create mode 100644 tests/cases/compiler/omitTypeTests01.ts diff --git a/tests/cases/compiler/omitTypeTestErrors01.ts b/tests/cases/compiler/omitTypeTestErrors01.ts new file mode 100644 index 0000000000000..fd3f5fc1e5d2a --- /dev/null +++ b/tests/cases/compiler/omitTypeTestErrors01.ts @@ -0,0 +1,19 @@ +// @declaration: true + +interface Foo { + a: string; + b: number; + c: boolean; +} + +export type Bar = Omit; +export type Baz = Omit; + +export function getBarC(bar: Bar) { + return bar.c; +} + +export function getBazB(baz: Baz) { + return baz.b; +} + diff --git a/tests/cases/compiler/omitTypeTests01.ts b/tests/cases/compiler/omitTypeTests01.ts new file mode 100644 index 0000000000000..d3b2ce26e1ec4 --- /dev/null +++ b/tests/cases/compiler/omitTypeTests01.ts @@ -0,0 +1,19 @@ +// @declaration: true + +interface Foo { + a: string; + b: number; + c: boolean; +} + +export type Bar = Omit; +export type Baz = Omit; + +export function getBarA(bar: Bar) { + return bar.a; +} + +export function getBazA(baz: Baz) { + return baz.a; +} + From 622cb421373e47cac3672795b64748723734570f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 24 Apr 2019 16:45:30 -0700 Subject: [PATCH 10/33] Accepted baselines. --- .../reference/omitTypeTestErrors01.errors.txt | 27 +++++++++++ .../reference/omitTypeTestErrors01.js | 44 +++++++++++++++++ .../reference/omitTypeTestErrors01.symbols | 43 +++++++++++++++++ .../reference/omitTypeTestErrors01.types | 39 +++++++++++++++ tests/baselines/reference/omitTypeTests01.js | 44 +++++++++++++++++ .../reference/omitTypeTests01.symbols | 47 +++++++++++++++++++ .../baselines/reference/omitTypeTests01.types | 39 +++++++++++++++ 7 files changed, 283 insertions(+) create mode 100644 tests/baselines/reference/omitTypeTestErrors01.errors.txt create mode 100644 tests/baselines/reference/omitTypeTestErrors01.js create mode 100644 tests/baselines/reference/omitTypeTestErrors01.symbols create mode 100644 tests/baselines/reference/omitTypeTestErrors01.types create mode 100644 tests/baselines/reference/omitTypeTests01.js create mode 100644 tests/baselines/reference/omitTypeTests01.symbols create mode 100644 tests/baselines/reference/omitTypeTests01.types diff --git a/tests/baselines/reference/omitTypeTestErrors01.errors.txt b/tests/baselines/reference/omitTypeTestErrors01.errors.txt new file mode 100644 index 0000000000000..a66ab384b8935 --- /dev/null +++ b/tests/baselines/reference/omitTypeTestErrors01.errors.txt @@ -0,0 +1,27 @@ +tests/cases/compiler/omitTypeTestErrors01.ts(11,16): error TS2339: Property 'c' does not exist on type 'Pick'. +tests/cases/compiler/omitTypeTestErrors01.ts(15,16): error TS2339: Property 'b' does not exist on type 'Pick'. + + +==== tests/cases/compiler/omitTypeTestErrors01.ts (2 errors) ==== + interface Foo { + a: string; + b: number; + c: boolean; + } + + export type Bar = Omit; + export type Baz = Omit; + + export function getBarC(bar: Bar) { + return bar.c; + ~ +!!! error TS2339: Property 'c' does not exist on type 'Pick'. + } + + export function getBazB(baz: Baz) { + return baz.b; + ~ +!!! error TS2339: Property 'b' does not exist on type 'Pick'. + } + + \ No newline at end of file diff --git a/tests/baselines/reference/omitTypeTestErrors01.js b/tests/baselines/reference/omitTypeTestErrors01.js new file mode 100644 index 0000000000000..03f1f5cc6b7b6 --- /dev/null +++ b/tests/baselines/reference/omitTypeTestErrors01.js @@ -0,0 +1,44 @@ +//// [omitTypeTestErrors01.ts] +interface Foo { + a: string; + b: number; + c: boolean; +} + +export type Bar = Omit; +export type Baz = Omit; + +export function getBarC(bar: Bar) { + return bar.c; +} + +export function getBazB(baz: Baz) { + return baz.b; +} + + + +//// [omitTypeTestErrors01.js] +"use strict"; +exports.__esModule = true; +function getBarC(bar) { + return bar.c; +} +exports.getBarC = getBarC; +function getBazB(baz) { + return baz.b; +} +exports.getBazB = getBazB; + + +//// [omitTypeTestErrors01.d.ts] +interface Foo { + a: string; + b: number; + c: boolean; +} +export declare type Bar = Omit; +export declare type Baz = Omit; +export declare function getBarC(bar: Bar): any; +export declare function getBazB(baz: Baz): any; +export {}; diff --git a/tests/baselines/reference/omitTypeTestErrors01.symbols b/tests/baselines/reference/omitTypeTestErrors01.symbols new file mode 100644 index 0000000000000..b913e20de4f93 --- /dev/null +++ b/tests/baselines/reference/omitTypeTestErrors01.symbols @@ -0,0 +1,43 @@ +=== tests/cases/compiler/omitTypeTestErrors01.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(omitTypeTestErrors01.ts, 0, 0)) + + a: string; +>a : Symbol(Foo.a, Decl(omitTypeTestErrors01.ts, 0, 15)) + + b: number; +>b : Symbol(Foo.b, Decl(omitTypeTestErrors01.ts, 1, 14)) + + c: boolean; +>c : Symbol(Foo.c, Decl(omitTypeTestErrors01.ts, 2, 14)) +} + +export type Bar = Omit; +>Bar : Symbol(Bar, Decl(omitTypeTestErrors01.ts, 4, 1)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>Foo : Symbol(Foo, Decl(omitTypeTestErrors01.ts, 0, 0)) + +export type Baz = Omit; +>Baz : Symbol(Baz, Decl(omitTypeTestErrors01.ts, 6, 33)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>Foo : Symbol(Foo, Decl(omitTypeTestErrors01.ts, 0, 0)) + +export function getBarC(bar: Bar) { +>getBarC : Symbol(getBarC, Decl(omitTypeTestErrors01.ts, 7, 39)) +>bar : Symbol(bar, Decl(omitTypeTestErrors01.ts, 9, 24)) +>Bar : Symbol(Bar, Decl(omitTypeTestErrors01.ts, 4, 1)) + + return bar.c; +>bar : Symbol(bar, Decl(omitTypeTestErrors01.ts, 9, 24)) +} + +export function getBazB(baz: Baz) { +>getBazB : Symbol(getBazB, Decl(omitTypeTestErrors01.ts, 11, 1)) +>baz : Symbol(baz, Decl(omitTypeTestErrors01.ts, 13, 24)) +>Baz : Symbol(Baz, Decl(omitTypeTestErrors01.ts, 6, 33)) + + return baz.b; +>baz : Symbol(baz, Decl(omitTypeTestErrors01.ts, 13, 24)) +} + + diff --git a/tests/baselines/reference/omitTypeTestErrors01.types b/tests/baselines/reference/omitTypeTestErrors01.types new file mode 100644 index 0000000000000..e7282016868d6 --- /dev/null +++ b/tests/baselines/reference/omitTypeTestErrors01.types @@ -0,0 +1,39 @@ +=== tests/cases/compiler/omitTypeTestErrors01.ts === +interface Foo { + a: string; +>a : string + + b: number; +>b : number + + c: boolean; +>c : boolean +} + +export type Bar = Omit; +>Bar : Pick + +export type Baz = Omit; +>Baz : Pick + +export function getBarC(bar: Bar) { +>getBarC : (bar: Pick) => any +>bar : Pick + + return bar.c; +>bar.c : any +>bar : Pick +>c : any +} + +export function getBazB(baz: Baz) { +>getBazB : (baz: Pick) => any +>baz : Pick + + return baz.b; +>baz.b : any +>baz : Pick +>b : any +} + + diff --git a/tests/baselines/reference/omitTypeTests01.js b/tests/baselines/reference/omitTypeTests01.js new file mode 100644 index 0000000000000..af244b8b02b39 --- /dev/null +++ b/tests/baselines/reference/omitTypeTests01.js @@ -0,0 +1,44 @@ +//// [omitTypeTests01.ts] +interface Foo { + a: string; + b: number; + c: boolean; +} + +export type Bar = Omit; +export type Baz = Omit; + +export function getBarA(bar: Bar) { + return bar.a; +} + +export function getBazA(baz: Baz) { + return baz.a; +} + + + +//// [omitTypeTests01.js] +"use strict"; +exports.__esModule = true; +function getBarA(bar) { + return bar.a; +} +exports.getBarA = getBarA; +function getBazA(baz) { + return baz.a; +} +exports.getBazA = getBazA; + + +//// [omitTypeTests01.d.ts] +interface Foo { + a: string; + b: number; + c: boolean; +} +export declare type Bar = Omit; +export declare type Baz = Omit; +export declare function getBarA(bar: Bar): string; +export declare function getBazA(baz: Baz): string; +export {}; diff --git a/tests/baselines/reference/omitTypeTests01.symbols b/tests/baselines/reference/omitTypeTests01.symbols new file mode 100644 index 0000000000000..d614f65daff03 --- /dev/null +++ b/tests/baselines/reference/omitTypeTests01.symbols @@ -0,0 +1,47 @@ +=== tests/cases/compiler/omitTypeTests01.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(omitTypeTests01.ts, 0, 0)) + + a: string; +>a : Symbol(Foo.a, Decl(omitTypeTests01.ts, 0, 15)) + + b: number; +>b : Symbol(Foo.b, Decl(omitTypeTests01.ts, 1, 14)) + + c: boolean; +>c : Symbol(Foo.c, Decl(omitTypeTests01.ts, 2, 14)) +} + +export type Bar = Omit; +>Bar : Symbol(Bar, Decl(omitTypeTests01.ts, 4, 1)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>Foo : Symbol(Foo, Decl(omitTypeTests01.ts, 0, 0)) + +export type Baz = Omit; +>Baz : Symbol(Baz, Decl(omitTypeTests01.ts, 6, 33)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>Foo : Symbol(Foo, Decl(omitTypeTests01.ts, 0, 0)) + +export function getBarA(bar: Bar) { +>getBarA : Symbol(getBarA, Decl(omitTypeTests01.ts, 7, 39)) +>bar : Symbol(bar, Decl(omitTypeTests01.ts, 9, 24)) +>Bar : Symbol(Bar, Decl(omitTypeTests01.ts, 4, 1)) + + return bar.a; +>bar.a : Symbol(a, Decl(omitTypeTests01.ts, 0, 15)) +>bar : Symbol(bar, Decl(omitTypeTests01.ts, 9, 24)) +>a : Symbol(a, Decl(omitTypeTests01.ts, 0, 15)) +} + +export function getBazA(baz: Baz) { +>getBazA : Symbol(getBazA, Decl(omitTypeTests01.ts, 11, 1)) +>baz : Symbol(baz, Decl(omitTypeTests01.ts, 13, 24)) +>Baz : Symbol(Baz, Decl(omitTypeTests01.ts, 6, 33)) + + return baz.a; +>baz.a : Symbol(a, Decl(omitTypeTests01.ts, 0, 15)) +>baz : Symbol(baz, Decl(omitTypeTests01.ts, 13, 24)) +>a : Symbol(a, Decl(omitTypeTests01.ts, 0, 15)) +} + + diff --git a/tests/baselines/reference/omitTypeTests01.types b/tests/baselines/reference/omitTypeTests01.types new file mode 100644 index 0000000000000..c07894ee2dcf6 --- /dev/null +++ b/tests/baselines/reference/omitTypeTests01.types @@ -0,0 +1,39 @@ +=== tests/cases/compiler/omitTypeTests01.ts === +interface Foo { + a: string; +>a : string + + b: number; +>b : number + + c: boolean; +>c : boolean +} + +export type Bar = Omit; +>Bar : Pick + +export type Baz = Omit; +>Baz : Pick + +export function getBarA(bar: Bar) { +>getBarA : (bar: Pick) => string +>bar : Pick + + return bar.a; +>bar.a : string +>bar : Pick +>a : string +} + +export function getBazA(baz: Baz) { +>getBazA : (baz: Pick) => string +>baz : Pick + + return baz.a; +>baz.a : string +>baz : Pick +>a : string +} + + From 57938e6cc23ac8f9aededab1adc252b249153407 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 24 Apr 2019 16:57:20 -0700 Subject: [PATCH 11/33] Make `Omit` alias its own mapped type so that references to it never expand to `Pick<...>`. --- src/lib/es5.d.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index de4a612d3919f..994fb1d765330 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1446,7 +1446,9 @@ type Extract = T extends U ? T : never; /** * Construct a type with the properties of T except for those in type K. */ -type Omit = Pick>; +type Omit = { + [P in Exclude]: T[P] +}; /** * Exclude null and undefined from T From a34f9880ea86901c5fd3a749866e2dd9837560be Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 24 Apr 2019 17:01:28 -0700 Subject: [PATCH 12/33] Accepted baselines. --- .../reference/omitTypeTestErrors01.errors.txt | 8 ++++---- .../reference/omitTypeTestErrors01.types | 16 ++++++++-------- .../baselines/reference/omitTypeTests01.symbols | 8 ++++---- tests/baselines/reference/omitTypeTests01.types | 16 ++++++++-------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/baselines/reference/omitTypeTestErrors01.errors.txt b/tests/baselines/reference/omitTypeTestErrors01.errors.txt index a66ab384b8935..6b65e292b55f4 100644 --- a/tests/baselines/reference/omitTypeTestErrors01.errors.txt +++ b/tests/baselines/reference/omitTypeTestErrors01.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/omitTypeTestErrors01.ts(11,16): error TS2339: Property 'c' does not exist on type 'Pick'. -tests/cases/compiler/omitTypeTestErrors01.ts(15,16): error TS2339: Property 'b' does not exist on type 'Pick'. +tests/cases/compiler/omitTypeTestErrors01.ts(11,16): error TS2339: Property 'c' does not exist on type 'Omit'. +tests/cases/compiler/omitTypeTestErrors01.ts(15,16): error TS2339: Property 'b' does not exist on type 'Omit'. ==== tests/cases/compiler/omitTypeTestErrors01.ts (2 errors) ==== @@ -15,13 +15,13 @@ tests/cases/compiler/omitTypeTestErrors01.ts(15,16): error TS2339: Property 'b' export function getBarC(bar: Bar) { return bar.c; ~ -!!! error TS2339: Property 'c' does not exist on type 'Pick'. +!!! error TS2339: Property 'c' does not exist on type 'Omit'. } export function getBazB(baz: Baz) { return baz.b; ~ -!!! error TS2339: Property 'b' does not exist on type 'Pick'. +!!! error TS2339: Property 'b' does not exist on type 'Omit'. } \ No newline at end of file diff --git a/tests/baselines/reference/omitTypeTestErrors01.types b/tests/baselines/reference/omitTypeTestErrors01.types index e7282016868d6..4b286c2c89cbf 100644 --- a/tests/baselines/reference/omitTypeTestErrors01.types +++ b/tests/baselines/reference/omitTypeTestErrors01.types @@ -11,28 +11,28 @@ interface Foo { } export type Bar = Omit; ->Bar : Pick +>Bar : Omit export type Baz = Omit; ->Baz : Pick +>Baz : Omit export function getBarC(bar: Bar) { ->getBarC : (bar: Pick) => any ->bar : Pick +>getBarC : (bar: Omit) => any +>bar : Omit return bar.c; >bar.c : any ->bar : Pick +>bar : Omit >c : any } export function getBazB(baz: Baz) { ->getBazB : (baz: Pick) => any ->baz : Pick +>getBazB : (baz: Omit) => any +>baz : Omit return baz.b; >baz.b : any ->baz : Pick +>baz : Omit >b : any } diff --git a/tests/baselines/reference/omitTypeTests01.symbols b/tests/baselines/reference/omitTypeTests01.symbols index d614f65daff03..93b492917855a 100644 --- a/tests/baselines/reference/omitTypeTests01.symbols +++ b/tests/baselines/reference/omitTypeTests01.symbols @@ -28,9 +28,9 @@ export function getBarA(bar: Bar) { >Bar : Symbol(Bar, Decl(omitTypeTests01.ts, 4, 1)) return bar.a; ->bar.a : Symbol(a, Decl(omitTypeTests01.ts, 0, 15)) +>bar.a : Symbol(a) >bar : Symbol(bar, Decl(omitTypeTests01.ts, 9, 24)) ->a : Symbol(a, Decl(omitTypeTests01.ts, 0, 15)) +>a : Symbol(a) } export function getBazA(baz: Baz) { @@ -39,9 +39,9 @@ export function getBazA(baz: Baz) { >Baz : Symbol(Baz, Decl(omitTypeTests01.ts, 6, 33)) return baz.a; ->baz.a : Symbol(a, Decl(omitTypeTests01.ts, 0, 15)) +>baz.a : Symbol(a) >baz : Symbol(baz, Decl(omitTypeTests01.ts, 13, 24)) ->a : Symbol(a, Decl(omitTypeTests01.ts, 0, 15)) +>a : Symbol(a) } diff --git a/tests/baselines/reference/omitTypeTests01.types b/tests/baselines/reference/omitTypeTests01.types index c07894ee2dcf6..549fcccc0f2f8 100644 --- a/tests/baselines/reference/omitTypeTests01.types +++ b/tests/baselines/reference/omitTypeTests01.types @@ -11,28 +11,28 @@ interface Foo { } export type Bar = Omit; ->Bar : Pick +>Bar : Omit export type Baz = Omit; ->Baz : Pick +>Baz : Omit export function getBarA(bar: Bar) { ->getBarA : (bar: Pick) => string ->bar : Pick +>getBarA : (bar: Omit) => string +>bar : Omit return bar.a; >bar.a : string ->bar : Pick +>bar : Omit >a : string } export function getBazA(baz: Baz) { ->getBazA : (baz: Pick) => string ->baz : Pick +>getBazA : (baz: Omit) => string +>baz : Omit return baz.a; >baz.a : string ->baz : Pick +>baz : Omit >a : string } From bc46c770bf304e8034fd90e01f00a4d506588c49 Mon Sep 17 00:00:00 2001 From: Wenlu Wang Date: Thu, 25 Apr 2019 12:09:21 -0500 Subject: [PATCH 13/33] allow literan enum const assertions (#30700) * allow literan enum const assertions * update desc --- src/compiler/checker.ts | 9 +- src/compiler/diagnosticMessages.json | 2 +- .../reference/constAssertions.errors.txt | 12 +- .../reference/constantEnumAssert.errors.txt | 59 ++++++ .../baselines/reference/constantEnumAssert.js | 85 +++++++++ .../reference/constantEnumAssert.symbols | 140 ++++++++++++++ .../reference/constantEnumAssert.types | 172 ++++++++++++++++++ tests/cases/compiler/constantEnumAssert.ts | 49 +++++ 8 files changed, 520 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/constantEnumAssert.errors.txt create mode 100644 tests/baselines/reference/constantEnumAssert.js create mode 100644 tests/baselines/reference/constantEnumAssert.symbols create mode 100644 tests/baselines/reference/constantEnumAssert.types create mode 100644 tests/cases/compiler/constantEnumAssert.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ce56db4b962f4..97bfa81630db2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21973,6 +21973,13 @@ namespace ts { const arg = (node).operand; return op === SyntaxKind.MinusToken && (arg.kind === SyntaxKind.NumericLiteral || arg.kind === SyntaxKind.BigIntLiteral) || op === SyntaxKind.PlusToken && arg.kind === SyntaxKind.NumericLiteral; + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + const expr = (node).expression; + if (isIdentifier(expr)) { + const symbol = getSymbolAtLocation(expr); + return !!(symbol && (symbol.flags & SymbolFlags.Enum) && getEnumKind(symbol) === EnumKind.Literal); + } } return false; } @@ -21981,7 +21988,7 @@ namespace ts { let exprType = checkExpression(expression, checkMode); if (isConstTypeReference(type)) { if (!isValidConstAssertionArgument(expression)) { - error(expression, Diagnostics.A_const_assertion_can_only_be_applied_to_a_string_number_boolean_array_or_object_literal); + error(expression, Diagnostics.A_const_assertions_can_only_be_applied_to_references_to_enum_members_or_string_number_boolean_array_or_object_literals); } return getRegularTypeOfLiteralType(exprType); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index a78e89f42beb3..04d8213dacbc6 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1031,7 +1031,7 @@ "category": "Error", "code": 1354 }, - "A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.": { + "A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.": { "category": "Error", "code": 1355 }, diff --git a/tests/baselines/reference/constAssertions.errors.txt b/tests/baselines/reference/constAssertions.errors.txt index 24fce1599012a..8ecce1377e344 100644 --- a/tests/baselines/reference/constAssertions.errors.txt +++ b/tests/baselines/reference/constAssertions.errors.txt @@ -1,7 +1,7 @@ tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(44,32): error TS2540: Cannot assign to 'x' because it is a read-only property. -tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(61,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal. -tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(62,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal. -tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(63,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal. +tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(61,10): error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. +tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(62,10): error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. +tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(63,10): error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. ==== tests/cases/conformance/expressions/typeAssertions/constAssertions.ts (4 errors) ==== @@ -69,11 +69,11 @@ tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(63,10): er let e1 = v1 as const; // Error ~~ -!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal. +!!! error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. let e2 = (true ? 1 : 0) as const; // Error ~~~~~~~~~~~~~~ -!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal. +!!! error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. let e3 = id(1) as const; // Error ~~~~~ -!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal. +!!! error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. \ No newline at end of file diff --git a/tests/baselines/reference/constantEnumAssert.errors.txt b/tests/baselines/reference/constantEnumAssert.errors.txt new file mode 100644 index 0000000000000..b384d3bd308e0 --- /dev/null +++ b/tests/baselines/reference/constantEnumAssert.errors.txt @@ -0,0 +1,59 @@ +tests/cases/compiler/constantEnumAssert.ts(45,20): error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. +tests/cases/compiler/constantEnumAssert.ts(49,20): error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. + + +==== tests/cases/compiler/constantEnumAssert.ts (2 errors) ==== + enum E1 { + a, + b + } + + enum E2 { + a = 'a', + b = 'b' + } + + enum E3 { + a = 1, + b = a << 1, + c = a << 2, + } + + const enum E4 { + a, + b + } + + const E5 = { + a: 'a', + b: 'b' + } + + const foo1 = { a: E1.a } + + const foo2 = { a: E2.a } + + const foo3 = { a: E1.a } as const + + const foo4 = { a: E2.a } as const + + const foo5 = { a: E3.a } as const + + const foo6 = { a: E4.a } as const + + const foo7 = { a: E5.a } as const + + const foo8 = { a: E1.a as const } + + const foo9 = { a: E2.a as const } + + const foo10 = { a: E3.a as const } + ~~~~ +!!! error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. + + const foo11 = { a: E4.a as const } + + const foo12 = { a: E5.a as const } + ~~~~ +!!! error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals. + \ No newline at end of file diff --git a/tests/baselines/reference/constantEnumAssert.js b/tests/baselines/reference/constantEnumAssert.js new file mode 100644 index 0000000000000..85f3db9d93a77 --- /dev/null +++ b/tests/baselines/reference/constantEnumAssert.js @@ -0,0 +1,85 @@ +//// [constantEnumAssert.ts] +enum E1 { + a, + b +} + +enum E2 { + a = 'a', + b = 'b' +} + +enum E3 { + a = 1, + b = a << 1, + c = a << 2, +} + +const enum E4 { + a, + b +} + +const E5 = { + a: 'a', + b: 'b' +} + +const foo1 = { a: E1.a } + +const foo2 = { a: E2.a } + +const foo3 = { a: E1.a } as const + +const foo4 = { a: E2.a } as const + +const foo5 = { a: E3.a } as const + +const foo6 = { a: E4.a } as const + +const foo7 = { a: E5.a } as const + +const foo8 = { a: E1.a as const } + +const foo9 = { a: E2.a as const } + +const foo10 = { a: E3.a as const } + +const foo11 = { a: E4.a as const } + +const foo12 = { a: E5.a as const } + + +//// [constantEnumAssert.js] +var E1; +(function (E1) { + E1[E1["a"] = 0] = "a"; + E1[E1["b"] = 1] = "b"; +})(E1 || (E1 = {})); +var E2; +(function (E2) { + E2["a"] = "a"; + E2["b"] = "b"; +})(E2 || (E2 = {})); +var E3; +(function (E3) { + E3[E3["a"] = 1] = "a"; + E3[E3["b"] = 2] = "b"; + E3[E3["c"] = 4] = "c"; +})(E3 || (E3 = {})); +var E5 = { + a: 'a', + b: 'b' +}; +var foo1 = { a: E1.a }; +var foo2 = { a: E2.a }; +var foo3 = { a: E1.a }; +var foo4 = { a: E2.a }; +var foo5 = { a: E3.a }; +var foo6 = { a: 0 /* a */ }; +var foo7 = { a: E5.a }; +var foo8 = { a: E1.a }; +var foo9 = { a: E2.a }; +var foo10 = { a: E3.a }; +var foo11 = { a: 0 /* a */ }; +var foo12 = { a: E5.a }; diff --git a/tests/baselines/reference/constantEnumAssert.symbols b/tests/baselines/reference/constantEnumAssert.symbols new file mode 100644 index 0000000000000..3249dbe61ccaa --- /dev/null +++ b/tests/baselines/reference/constantEnumAssert.symbols @@ -0,0 +1,140 @@ +=== tests/cases/compiler/constantEnumAssert.ts === +enum E1 { +>E1 : Symbol(E1, Decl(constantEnumAssert.ts, 0, 0)) + + a, +>a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9)) + + b +>b : Symbol(E1.b, Decl(constantEnumAssert.ts, 1, 6)) +} + +enum E2 { +>E2 : Symbol(E2, Decl(constantEnumAssert.ts, 3, 1)) + + a = 'a', +>a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9)) + + b = 'b' +>b : Symbol(E2.b, Decl(constantEnumAssert.ts, 6, 12)) +} + +enum E3 { +>E3 : Symbol(E3, Decl(constantEnumAssert.ts, 8, 1)) + + a = 1, +>a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9)) + + b = a << 1, +>b : Symbol(E3.b, Decl(constantEnumAssert.ts, 11, 10)) +>a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9)) + + c = a << 2, +>c : Symbol(E3.c, Decl(constantEnumAssert.ts, 12, 15)) +>a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9)) +} + +const enum E4 { +>E4 : Symbol(E4, Decl(constantEnumAssert.ts, 14, 1)) + + a, +>a : Symbol(E4.a, Decl(constantEnumAssert.ts, 16, 15)) + + b +>b : Symbol(E4.b, Decl(constantEnumAssert.ts, 17, 6)) +} + +const E5 = { +>E5 : Symbol(E5, Decl(constantEnumAssert.ts, 21, 5)) + + a: 'a', +>a : Symbol(a, Decl(constantEnumAssert.ts, 21, 12)) + + b: 'b' +>b : Symbol(b, Decl(constantEnumAssert.ts, 22, 11)) +} + +const foo1 = { a: E1.a } +>foo1 : Symbol(foo1, Decl(constantEnumAssert.ts, 26, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 26, 14)) +>E1.a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9)) +>E1 : Symbol(E1, Decl(constantEnumAssert.ts, 0, 0)) +>a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9)) + +const foo2 = { a: E2.a } +>foo2 : Symbol(foo2, Decl(constantEnumAssert.ts, 28, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 28, 14)) +>E2.a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9)) +>E2 : Symbol(E2, Decl(constantEnumAssert.ts, 3, 1)) +>a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9)) + +const foo3 = { a: E1.a } as const +>foo3 : Symbol(foo3, Decl(constantEnumAssert.ts, 30, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 30, 14)) +>E1.a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9)) +>E1 : Symbol(E1, Decl(constantEnumAssert.ts, 0, 0)) +>a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9)) + +const foo4 = { a: E2.a } as const +>foo4 : Symbol(foo4, Decl(constantEnumAssert.ts, 32, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 32, 14)) +>E2.a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9)) +>E2 : Symbol(E2, Decl(constantEnumAssert.ts, 3, 1)) +>a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9)) + +const foo5 = { a: E3.a } as const +>foo5 : Symbol(foo5, Decl(constantEnumAssert.ts, 34, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 34, 14)) +>E3.a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9)) +>E3 : Symbol(E3, Decl(constantEnumAssert.ts, 8, 1)) +>a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9)) + +const foo6 = { a: E4.a } as const +>foo6 : Symbol(foo6, Decl(constantEnumAssert.ts, 36, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 36, 14)) +>E4.a : Symbol(E4.a, Decl(constantEnumAssert.ts, 16, 15)) +>E4 : Symbol(E4, Decl(constantEnumAssert.ts, 14, 1)) +>a : Symbol(E4.a, Decl(constantEnumAssert.ts, 16, 15)) + +const foo7 = { a: E5.a } as const +>foo7 : Symbol(foo7, Decl(constantEnumAssert.ts, 38, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 38, 14)) +>E5.a : Symbol(a, Decl(constantEnumAssert.ts, 21, 12)) +>E5 : Symbol(E5, Decl(constantEnumAssert.ts, 21, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 21, 12)) + +const foo8 = { a: E1.a as const } +>foo8 : Symbol(foo8, Decl(constantEnumAssert.ts, 40, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 40, 14)) +>E1.a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9)) +>E1 : Symbol(E1, Decl(constantEnumAssert.ts, 0, 0)) +>a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9)) + +const foo9 = { a: E2.a as const } +>foo9 : Symbol(foo9, Decl(constantEnumAssert.ts, 42, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 42, 14)) +>E2.a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9)) +>E2 : Symbol(E2, Decl(constantEnumAssert.ts, 3, 1)) +>a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9)) + +const foo10 = { a: E3.a as const } +>foo10 : Symbol(foo10, Decl(constantEnumAssert.ts, 44, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 44, 15)) +>E3.a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9)) +>E3 : Symbol(E3, Decl(constantEnumAssert.ts, 8, 1)) +>a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9)) + +const foo11 = { a: E4.a as const } +>foo11 : Symbol(foo11, Decl(constantEnumAssert.ts, 46, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 46, 15)) +>E4.a : Symbol(E4.a, Decl(constantEnumAssert.ts, 16, 15)) +>E4 : Symbol(E4, Decl(constantEnumAssert.ts, 14, 1)) +>a : Symbol(E4.a, Decl(constantEnumAssert.ts, 16, 15)) + +const foo12 = { a: E5.a as const } +>foo12 : Symbol(foo12, Decl(constantEnumAssert.ts, 48, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 48, 15)) +>E5.a : Symbol(a, Decl(constantEnumAssert.ts, 21, 12)) +>E5 : Symbol(E5, Decl(constantEnumAssert.ts, 21, 5)) +>a : Symbol(a, Decl(constantEnumAssert.ts, 21, 12)) + diff --git a/tests/baselines/reference/constantEnumAssert.types b/tests/baselines/reference/constantEnumAssert.types new file mode 100644 index 0000000000000..36d4f7f3abcd4 --- /dev/null +++ b/tests/baselines/reference/constantEnumAssert.types @@ -0,0 +1,172 @@ +=== tests/cases/compiler/constantEnumAssert.ts === +enum E1 { +>E1 : E1 + + a, +>a : E1.a + + b +>b : E1.b +} + +enum E2 { +>E2 : E2 + + a = 'a', +>a : E2.a +>'a' : "a" + + b = 'b' +>b : E2.b +>'b' : "b" +} + +enum E3 { +>E3 : E3 + + a = 1, +>a : E3 +>1 : 1 + + b = a << 1, +>b : E3 +>a << 1 : number +>a : E3 +>1 : 1 + + c = a << 2, +>c : E3 +>a << 2 : number +>a : E3 +>2 : 2 +} + +const enum E4 { +>E4 : E4 + + a, +>a : E4.a + + b +>b : E4.b +} + +const E5 = { +>E5 : { a: string; b: string; } +>{ a: 'a', b: 'b'} : { a: string; b: string; } + + a: 'a', +>a : string +>'a' : "a" + + b: 'b' +>b : string +>'b' : "b" +} + +const foo1 = { a: E1.a } +>foo1 : { a: E1; } +>{ a: E1.a } : { a: E1; } +>a : E1 +>E1.a : E1.a +>E1 : typeof E1 +>a : E1.a + +const foo2 = { a: E2.a } +>foo2 : { a: E2; } +>{ a: E2.a } : { a: E2; } +>a : E2 +>E2.a : E2.a +>E2 : typeof E2 +>a : E2.a + +const foo3 = { a: E1.a } as const +>foo3 : { readonly a: E1.a; } +>{ a: E1.a } as const : { readonly a: E1.a; } +>{ a: E1.a } : { readonly a: E1.a; } +>a : E1.a +>E1.a : E1.a +>E1 : typeof E1 +>a : E1.a + +const foo4 = { a: E2.a } as const +>foo4 : { readonly a: E2.a; } +>{ a: E2.a } as const : { readonly a: E2.a; } +>{ a: E2.a } : { readonly a: E2.a; } +>a : E2.a +>E2.a : E2.a +>E2 : typeof E2 +>a : E2.a + +const foo5 = { a: E3.a } as const +>foo5 : { readonly a: E3; } +>{ a: E3.a } as const : { readonly a: E3; } +>{ a: E3.a } : { readonly a: E3; } +>a : E3 +>E3.a : E3 +>E3 : typeof E3 +>a : E3 + +const foo6 = { a: E4.a } as const +>foo6 : { readonly a: E4.a; } +>{ a: E4.a } as const : { readonly a: E4.a; } +>{ a: E4.a } : { readonly a: E4.a; } +>a : E4.a +>E4.a : E4.a +>E4 : typeof E4 +>a : E4.a + +const foo7 = { a: E5.a } as const +>foo7 : { readonly a: string; } +>{ a: E5.a } as const : { readonly a: string; } +>{ a: E5.a } : { readonly a: string; } +>a : string +>E5.a : string +>E5 : { a: string; b: string; } +>a : string + +const foo8 = { a: E1.a as const } +>foo8 : { a: E1.a; } +>{ a: E1.a as const } : { a: E1.a; } +>a : E1.a +>E1.a as const : E1.a +>E1.a : E1.a +>E1 : typeof E1 +>a : E1.a + +const foo9 = { a: E2.a as const } +>foo9 : { a: E2.a; } +>{ a: E2.a as const } : { a: E2.a; } +>a : E2.a +>E2.a as const : E2.a +>E2.a : E2.a +>E2 : typeof E2 +>a : E2.a + +const foo10 = { a: E3.a as const } +>foo10 : { a: E3; } +>{ a: E3.a as const } : { a: E3; } +>a : E3 +>E3.a as const : E3 +>E3.a : E3 +>E3 : typeof E3 +>a : E3 + +const foo11 = { a: E4.a as const } +>foo11 : { a: E4.a; } +>{ a: E4.a as const } : { a: E4.a; } +>a : E4.a +>E4.a as const : E4.a +>E4.a : E4.a +>E4 : typeof E4 +>a : E4.a + +const foo12 = { a: E5.a as const } +>foo12 : { a: string; } +>{ a: E5.a as const } : { a: string; } +>a : string +>E5.a as const : string +>E5.a : string +>E5 : { a: string; b: string; } +>a : string + diff --git a/tests/cases/compiler/constantEnumAssert.ts b/tests/cases/compiler/constantEnumAssert.ts new file mode 100644 index 0000000000000..d57845a7edfdd --- /dev/null +++ b/tests/cases/compiler/constantEnumAssert.ts @@ -0,0 +1,49 @@ +enum E1 { + a, + b +} + +enum E2 { + a = 'a', + b = 'b' +} + +enum E3 { + a = 1, + b = a << 1, + c = a << 2, +} + +const enum E4 { + a, + b +} + +const E5 = { + a: 'a', + b: 'b' +} + +const foo1 = { a: E1.a } + +const foo2 = { a: E2.a } + +const foo3 = { a: E1.a } as const + +const foo4 = { a: E2.a } as const + +const foo5 = { a: E3.a } as const + +const foo6 = { a: E4.a } as const + +const foo7 = { a: E5.a } as const + +const foo8 = { a: E1.a as const } + +const foo9 = { a: E2.a as const } + +const foo10 = { a: E3.a as const } + +const foo11 = { a: E4.a as const } + +const foo12 = { a: E5.a as const } From e007ccf97bc526ff1f45a1f84c26758973c10daa Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 25 Apr 2019 10:38:20 -0700 Subject: [PATCH 14/33] Simplify chaining of transforms (#22994) --- src/compiler/core.ts | 33 --------------------------------- src/compiler/transformer.ts | 8 +++++++- 2 files changed, 7 insertions(+), 34 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index b99304ddfedca..b3839842d3e60 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1639,39 +1639,6 @@ namespace ts { }; } - /** - * High-order function, creates a function that executes a function composition. - * For example, `chain(a, b)` is the equivalent of `x => ((a', b') => y => b'(a'(y)))(a(x), b(x))` - * - * @param args The functions to chain. - */ - export function chain(...args: ((t: T) => (u: U) => U)[]): (t: T) => (u: U) => U; - export function chain(a: (t: T) => (u: U) => U, b: (t: T) => (u: U) => U, c: (t: T) => (u: U) => U, d: (t: T) => (u: U) => U, e: (t: T) => (u: U) => U): (t: T) => (u: U) => U { - if (e) { - const args: ((t: T) => (u: U) => U)[] = []; - for (let i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } - - return t => compose(...map(args, f => f(t))); - } - else if (d) { - return t => compose(a(t), b(t), c(t), d(t)); - } - else if (c) { - return t => compose(a(t), b(t), c(t)); - } - else if (b) { - return t => compose(a(t), b(t)); - } - else if (a) { - return t => compose(a(t)); - } - else { - return _ => u => u; - } - } - /** * High-order function, composes functions. Note that functions are composed inside-out; * for example, `compose(a, b)` is the equivalent of `x => b(a(x))`. diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 12d20d6c089eb..ba47d5b8106ff 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -151,7 +151,13 @@ namespace ts { performance.mark("beforeTransform"); // Chain together and initialize each transformer. - const transformation = chain(...transformers)(context); + const transformersWithContext = transformers.map(t => t(context)); + const transformation = (node: T): T => { + for (const transform of transformersWithContext) { + node = transform(node); + } + return node; + }; // prevent modification of transformation hooks. state = TransformationState.Initialized; From 583edce6b0505e12a4627902147141661ca1b256 Mon Sep 17 00:00:00 2001 From: Wenlu Wang Date: Thu, 25 Apr 2019 12:51:36 -0500 Subject: [PATCH 15/33] fix compiler crash (#25925) --- src/compiler/transformers/ts.ts | 2 +- tests/baselines/reference/constEnum4.js | 13 +++++++++++++ tests/baselines/reference/constEnum4.symbols | 13 +++++++++++++ tests/baselines/reference/constEnum4.types | 17 +++++++++++++++++ .../cases/conformance/constEnums/constEnum4.ts | 6 ++++++ 5 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/constEnum4.js create mode 100644 tests/baselines/reference/constEnum4.symbols create mode 100644 tests/baselines/reference/constEnum4.types create mode 100644 tests/cases/conformance/constEnums/constEnum4.ts diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 63d621c665439..a70fb820e7950 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2577,7 +2577,7 @@ namespace ts { */ function visitEnumDeclaration(node: EnumDeclaration): VisitResult { if (!shouldEmitEnumDeclaration(node)) { - return undefined; + return createNotEmittedStatement(node); } const statements: Statement[] = []; diff --git a/tests/baselines/reference/constEnum4.js b/tests/baselines/reference/constEnum4.js new file mode 100644 index 0000000000000..dc7c4b0e593ec --- /dev/null +++ b/tests/baselines/reference/constEnum4.js @@ -0,0 +1,13 @@ +//// [constEnum4.ts] +if (1) + const enum A { } +else if (2) + const enum B { } +else + const enum C { } + + +//// [constEnum4.js] +if (1) +else if (2) +else diff --git a/tests/baselines/reference/constEnum4.symbols b/tests/baselines/reference/constEnum4.symbols new file mode 100644 index 0000000000000..0098e85c130ea --- /dev/null +++ b/tests/baselines/reference/constEnum4.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/constEnums/constEnum4.ts === +if (1) + const enum A { } +>A : Symbol(A, Decl(constEnum4.ts, 0, 6)) + +else if (2) + const enum B { } +>B : Symbol(B, Decl(constEnum4.ts, 2, 11)) + +else + const enum C { } +>C : Symbol(C, Decl(constEnum4.ts, 4, 4)) + diff --git a/tests/baselines/reference/constEnum4.types b/tests/baselines/reference/constEnum4.types new file mode 100644 index 0000000000000..a35e9f898bf8e --- /dev/null +++ b/tests/baselines/reference/constEnum4.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/constEnums/constEnum4.ts === +if (1) +>1 : 1 + + const enum A { } +>A : A + +else if (2) +>2 : 2 + + const enum B { } +>B : B + +else + const enum C { } +>C : C + diff --git a/tests/cases/conformance/constEnums/constEnum4.ts b/tests/cases/conformance/constEnums/constEnum4.ts new file mode 100644 index 0000000000000..c6dc5840c4682 --- /dev/null +++ b/tests/cases/conformance/constEnums/constEnum4.ts @@ -0,0 +1,6 @@ +if (1) + const enum A { } +else if (2) + const enum B { } +else + const enum C { } From 6e4c150d6b70d2febef0f883b1a32c3a259f24b0 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 25 Apr 2019 10:53:39 -0700 Subject: [PATCH 16/33] When function parameters span multiple lines, make the function span start at the `(` (#26907) * When function parameters span multiple lines, make the function span start at the `(` * Undo unnecessary change --- src/compiler/utilities.ts | 4 +++ src/services/outliningElementsCollector.ts | 26 ++++++++++++------- .../fourslash/outliningSpansForFunction.ts | 14 ++++++++++ 3 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 tests/cases/fourslash/outliningSpansForFunction.ts diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 2e6c3ae4f866e..7deb2c823cdc1 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4330,6 +4330,10 @@ namespace ts { return positionsAreOnSameLine(range1.end, getStartPositionOfRange(range2, sourceFile), sourceFile); } + export function isNodeArrayMultiLine(list: NodeArray, sourceFile: SourceFile): boolean { + return !positionsAreOnSameLine(list.pos, list.end, sourceFile); + } + export function positionsAreOnSameLine(pos1: number, pos2: number, sourceFile: SourceFile) { return pos1 === pos2 || getLineOfLocalPosition(sourceFile, pos1) === getLineOfLocalPosition(sourceFile, pos2); diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 6f834512f0b48..650a107f4a5e7 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -153,8 +153,8 @@ namespace ts.OutliningElementsCollector { function getOutliningSpanForNode(n: Node, sourceFile: SourceFile): OutliningSpan | undefined { switch (n.kind) { case SyntaxKind.Block: - if (isFunctionBlock(n)) { - return spanForNode(n.parent, /*autoCollapse*/ n.parent.kind !== SyntaxKind.ArrowFunction); + if (isFunctionLike(n.parent)) { + return functionSpan(n.parent, n as Block, sourceFile); } // Check if the block is standalone, or 'attached' to some parent statement. // If the latter, we want to collapse the block, but consider its hint span @@ -225,18 +225,26 @@ namespace ts.OutliningElementsCollector { return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !isArrayLiteralExpression(node.parent) && !isCallExpression(node.parent), open); } - function spanForNode(hintSpanNode: Node, autoCollapse = false, useFullStart = true, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken): OutliningSpan | undefined { + function spanForNode(hintSpanNode: Node, autoCollapse = false, useFullStart = true, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken, close: SyntaxKind = open === SyntaxKind.OpenBraceToken ? SyntaxKind.CloseBraceToken : SyntaxKind.CloseBracketToken): OutliningSpan | undefined { const openToken = findChildOfKind(n, open, sourceFile); - const close = open === SyntaxKind.OpenBraceToken ? SyntaxKind.CloseBraceToken : SyntaxKind.CloseBracketToken; const closeToken = findChildOfKind(n, close, sourceFile); - if (!openToken || !closeToken) { - return undefined; - } - const textSpan = createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd()); - return createOutliningSpan(textSpan, OutliningSpanKind.Code, createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse); + return openToken && closeToken && spanBetweenTokens(openToken, closeToken, hintSpanNode, sourceFile, autoCollapse, useFullStart); } } + function functionSpan(node: FunctionLike, body: Block, sourceFile: SourceFile): OutliningSpan | undefined { + const openToken = isNodeArrayMultiLine(node.parameters, sourceFile) + ? findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile) + : findChildOfKind(body, SyntaxKind.OpenBraceToken, sourceFile); + const closeToken = findChildOfKind(body, SyntaxKind.CloseBraceToken, sourceFile); + return openToken && closeToken && spanBetweenTokens(openToken, closeToken, node.parent, sourceFile, /*autoCollapse*/ node.parent.kind !== SyntaxKind.ArrowFunction); + } + + function spanBetweenTokens(openToken: Node, closeToken: Node, hintSpanNode: Node, sourceFile: SourceFile, autoCollapse = false, useFullStart = true): OutliningSpan { + const textSpan = createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd()); + return createOutliningSpan(textSpan, OutliningSpanKind.Code, createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse); + } + function createOutliningSpan(textSpan: TextSpan, kind: OutliningSpanKind, hintSpan: TextSpan = textSpan, autoCollapse = false, bannerText = "..."): OutliningSpan { return { textSpan, kind, hintSpan, bannerText, autoCollapse }; } diff --git a/tests/cases/fourslash/outliningSpansForFunction.ts b/tests/cases/fourslash/outliningSpansForFunction.ts new file mode 100644 index 0000000000000..acc00eedbee3a --- /dev/null +++ b/tests/cases/fourslash/outliningSpansForFunction.ts @@ -0,0 +1,14 @@ +/// + +////function f(x: number, y: number)[| { +//// return x + y; +////}|] +//// +////function g[|( +//// x: number, +//// y: number, +////): number { +//// return x + y; +////}|] + +verify.outliningSpansInCurrentFile(test.ranges()); From aafba363e483bc3aa2a0a964a61f5e12a44efe3b Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 25 Apr 2019 11:06:31 -0700 Subject: [PATCH 17/33] Avoid recalculating versionPaths in loadNodeModuleFromDirectory (#27537) * Avoid recalculating versionPaths in loadNodeModuleFromDirectory * Update baselines --- src/compiler/moduleNameResolver.ts | 2 +- tests/baselines/reference/library-reference-10.trace.json | 2 -- tests/baselines/reference/library-reference-2.trace.json | 2 -- tests/baselines/reference/typesVersions.justIndex.trace.json | 1 - ...onsDeclarationEmit.multiFileBackReferenceToSelf.trace.json | 1 - tests/baselines/reference/typingsLookup4.trace.json | 4 ---- 6 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index b8aa9fa2df465..590403addf7f6 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1106,7 +1106,7 @@ namespace ts { const packageInfo = considerPackageJson ? getPackageJsonInfo(candidate, "", onlyRecordFailures, state) : undefined; const packageId = packageInfo && packageInfo.packageId; const packageJsonContent = packageInfo && packageInfo.packageJsonContent; - const versionPaths = packageJsonContent && readPackageJsonTypesVersionPaths(packageJsonContent, state); + const versionPaths = packageInfo && packageInfo.versionPaths; return withPackageId(packageId, loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageJsonContent, versionPaths)); } diff --git a/tests/baselines/reference/library-reference-10.trace.json b/tests/baselines/reference/library-reference-10.trace.json index 3e6cf4432eaed..37f8ab543caee 100644 --- a/tests/baselines/reference/library-reference-10.trace.json +++ b/tests/baselines/reference/library-reference-10.trace.json @@ -4,7 +4,6 @@ "'package.json' has 'typings' field 'jquery.d.ts' that references 'types/jquery/jquery.d.ts'.", "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at './types/jquery/package.json'.", - "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'jquery.d.ts' that references 'types/jquery/jquery.d.ts'.", "File 'types/jquery/jquery.d.ts' exist - use it as a name resolution result.", "Resolving real path for 'types/jquery/jquery.d.ts', result '/foo/types/jquery/jquery.d.ts'.", @@ -14,7 +13,6 @@ "'package.json' has 'typings' field 'jquery.d.ts' that references 'types/jquery/jquery.d.ts'.", "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at './types/jquery/package.json'.", - "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'jquery.d.ts' that references 'types/jquery/jquery.d.ts'.", "File 'types/jquery/jquery.d.ts' exist - use it as a name resolution result.", "Resolving real path for 'types/jquery/jquery.d.ts', result '/foo/types/jquery/jquery.d.ts'.", diff --git a/tests/baselines/reference/library-reference-2.trace.json b/tests/baselines/reference/library-reference-2.trace.json index 8a13d1e6f5455..b9b4cf08ca2ce 100644 --- a/tests/baselines/reference/library-reference-2.trace.json +++ b/tests/baselines/reference/library-reference-2.trace.json @@ -5,7 +5,6 @@ "'package.json' has 'types' field 'jquery.d.ts' that references '/types/jquery/jquery.d.ts'.", "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/types/jquery/package.json'.", - "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'jquery.d.ts' that references '/types/jquery/jquery.d.ts'.", "File '/types/jquery/jquery.d.ts' exist - use it as a name resolution result.", @@ -17,7 +16,6 @@ "'package.json' has 'types' field 'jquery.d.ts' that references '/types/jquery/jquery.d.ts'.", "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/types/jquery/package.json'.", - "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'jquery.d.ts' that references '/types/jquery/jquery.d.ts'.", "File '/types/jquery/jquery.d.ts' exist - use it as a name resolution result.", diff --git a/tests/baselines/reference/typesVersions.justIndex.trace.json b/tests/baselines/reference/typesVersions.justIndex.trace.json index d69aa51f72ded..28e4a5cb3bfaf 100644 --- a/tests/baselines/reference/typesVersions.justIndex.trace.json +++ b/tests/baselines/reference/typesVersions.justIndex.trace.json @@ -12,7 +12,6 @@ "'package.json' does not have a 'main' field.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at '/a/package.json'.", - "'package.json' has a 'typesVersions' field with version-specific path mappings.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' does not have a 'main' field.", diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json index cf08a29478f1d..464da214bae2a 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json @@ -6,7 +6,6 @@ "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/ndex/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' field with version-specific path mappings.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.", diff --git a/tests/baselines/reference/typingsLookup4.trace.json b/tests/baselines/reference/typingsLookup4.trace.json index 86b386670d6a5..6409896ad1744 100644 --- a/tests/baselines/reference/typingsLookup4.trace.json +++ b/tests/baselines/reference/typingsLookup4.trace.json @@ -72,7 +72,6 @@ "'package.json' has 'typings' field 'jquery.d.ts' that references '/node_modules/@types/jquery/jquery.d.ts'.", "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/jquery/package.json'.", - "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'jquery.d.ts' that references '/node_modules/@types/jquery/jquery.d.ts'.", "File '/node_modules/@types/jquery/jquery.d.ts' exist - use it as a name resolution result.", "Resolving real path for '/node_modules/@types/jquery/jquery.d.ts', result '/node_modules/@types/jquery/jquery.d.ts'.", @@ -82,7 +81,6 @@ "'package.json' has 'typings' field 'kquery' that references '/node_modules/@types/kquery/kquery'.", "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/kquery/package.json'.", - "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'kquery' that references '/node_modules/@types/kquery/kquery'.", "File '/node_modules/@types/kquery/kquery' does not exist.", "Loading module as file / folder, candidate module location '/node_modules/@types/kquery/kquery', target file type 'TypeScript'.", @@ -96,7 +94,6 @@ "'package.json' has 'typings' field 'lquery' that references '/node_modules/@types/lquery/lquery'.", "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/lquery/package.json'.", - "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'lquery' that references '/node_modules/@types/lquery/lquery'.", "File '/node_modules/@types/lquery/lquery' does not exist.", "Loading module as file / folder, candidate module location '/node_modules/@types/lquery/lquery', target file type 'TypeScript'.", @@ -108,7 +105,6 @@ "'package.json' has 'typings' field 'mquery' that references '/node_modules/@types/mquery/mquery'.", "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/mquery/package.json'.", - "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'mquery' that references '/node_modules/@types/mquery/mquery'.", "File '/node_modules/@types/mquery/mquery' does not exist.", "Loading module as file / folder, candidate module location '/node_modules/@types/mquery/mquery', target file type 'TypeScript'.", From 591b25593d336cebab653949a114bdd38fc5268c Mon Sep 17 00:00:00 2001 From: Ely Alamillo Date: Thu, 25 Apr 2019 15:16:41 -0500 Subject: [PATCH 18/33] update error message and update baselines (#27628) --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- tests/baselines/reference/missingRequiredDeclare.d.errors.txt | 4 ++-- tests/baselines/reference/parserEnumDeclaration3.d.errors.txt | 4 ++-- .../reference/parserFunctionDeclaration2.d.errors.txt | 4 ++-- .../baselines/reference/parserModuleDeclaration1.d.errors.txt | 4 ++-- .../baselines/reference/parserModuleDeclaration2.d.errors.txt | 4 ++-- .../baselines/reference/parserModuleDeclaration4.d.errors.txt | 4 ++-- .../baselines/reference/parserVariableStatement1.d.errors.txt | 4 ++-- .../baselines/reference/parserVariableStatement2.d.errors.txt | 4 ++-- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 97bfa81630db2..9020d9e47dfd9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31848,7 +31848,7 @@ namespace ts { return false; } - return grammarErrorOnFirstToken(node, Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file); + return grammarErrorOnFirstToken(node, Diagnostics.Top_level_declarations_in_d_ts_files_must_start_with_either_a_declare_or_export_modifier); } function checkGrammarTopLevelElementsForRequiredDeclareModifier(file: SourceFile): boolean { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 04d8213dacbc6..befff38aee16b 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -139,7 +139,7 @@ "category": "Error", "code": 1045 }, - "A 'declare' modifier is required for a top level declaration in a .d.ts file.": { + "Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier.": { "category": "Error", "code": 1046 }, diff --git a/tests/baselines/reference/missingRequiredDeclare.d.errors.txt b/tests/baselines/reference/missingRequiredDeclare.d.errors.txt index a673c948a4873..079de0b022260 100644 --- a/tests/baselines/reference/missingRequiredDeclare.d.errors.txt +++ b/tests/baselines/reference/missingRequiredDeclare.d.errors.txt @@ -1,10 +1,10 @@ -tests/cases/compiler/missingRequiredDeclare.d.ts(1,1): error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +tests/cases/compiler/missingRequiredDeclare.d.ts(1,1): error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. tests/cases/compiler/missingRequiredDeclare.d.ts(1,9): error TS1039: Initializers are not allowed in ambient contexts. ==== tests/cases/compiler/missingRequiredDeclare.d.ts (2 errors) ==== var x = 1; ~~~ -!!! error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +!!! error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. ~ !!! error TS1039: Initializers are not allowed in ambient contexts. \ No newline at end of file diff --git a/tests/baselines/reference/parserEnumDeclaration3.d.errors.txt b/tests/baselines/reference/parserEnumDeclaration3.d.errors.txt index 03bba3492e77f..9be61012304b4 100644 --- a/tests/baselines/reference/parserEnumDeclaration3.d.errors.txt +++ b/tests/baselines/reference/parserEnumDeclaration3.d.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/EnumDeclarations/parserEnumDeclaration3.d.ts(1,1): error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +tests/cases/conformance/parser/ecmascript5/EnumDeclarations/parserEnumDeclaration3.d.ts(1,1): error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. ==== tests/cases/conformance/parser/ecmascript5/EnumDeclarations/parserEnumDeclaration3.d.ts (1 errors) ==== enum E { ~~~~ -!!! error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +!!! error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. A = 1 } \ No newline at end of file diff --git a/tests/baselines/reference/parserFunctionDeclaration2.d.errors.txt b/tests/baselines/reference/parserFunctionDeclaration2.d.errors.txt index 6f836544efc90..b682d1b1e3fe5 100644 --- a/tests/baselines/reference/parserFunctionDeclaration2.d.errors.txt +++ b/tests/baselines/reference/parserFunctionDeclaration2.d.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/parser/ecmascript5/FunctionDeclarations/parserFunctionDeclaration2.d.ts(1,1): error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +tests/cases/conformance/parser/ecmascript5/FunctionDeclarations/parserFunctionDeclaration2.d.ts(1,1): error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. tests/cases/conformance/parser/ecmascript5/FunctionDeclarations/parserFunctionDeclaration2.d.ts(1,14): error TS1183: An implementation cannot be declared in ambient contexts. ==== tests/cases/conformance/parser/ecmascript5/FunctionDeclarations/parserFunctionDeclaration2.d.ts (2 errors) ==== function F() { ~~~~~~~~ -!!! error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +!!! error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. ~ !!! error TS1183: An implementation cannot be declared in ambient contexts. } \ No newline at end of file diff --git a/tests/baselines/reference/parserModuleDeclaration1.d.errors.txt b/tests/baselines/reference/parserModuleDeclaration1.d.errors.txt index 4f5b3b581d18c..4c88d2a29946b 100644 --- a/tests/baselines/reference/parserModuleDeclaration1.d.errors.txt +++ b/tests/baselines/reference/parserModuleDeclaration1.d.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration1.d.ts(1,1): error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +tests/cases/conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration1.d.ts(1,1): error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. ==== tests/cases/conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration1.d.ts (1 errors) ==== module "Foo" { ~~~~~~ -!!! error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +!!! error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. } \ No newline at end of file diff --git a/tests/baselines/reference/parserModuleDeclaration2.d.errors.txt b/tests/baselines/reference/parserModuleDeclaration2.d.errors.txt index 00c2fbb82a0cb..6ff076949570c 100644 --- a/tests/baselines/reference/parserModuleDeclaration2.d.errors.txt +++ b/tests/baselines/reference/parserModuleDeclaration2.d.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration2.d.ts(1,1): error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +tests/cases/conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration2.d.ts(1,1): error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. ==== tests/cases/conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration2.d.ts (1 errors) ==== module M { ~~~~~~ -!!! error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +!!! error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. } \ No newline at end of file diff --git a/tests/baselines/reference/parserModuleDeclaration4.d.errors.txt b/tests/baselines/reference/parserModuleDeclaration4.d.errors.txt index 2e75c6cbc509a..107c44c453671 100644 --- a/tests/baselines/reference/parserModuleDeclaration4.d.errors.txt +++ b/tests/baselines/reference/parserModuleDeclaration4.d.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration4.d.ts(1,1): error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +tests/cases/conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration4.d.ts(1,1): error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. tests/cases/conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration4.d.ts(2,3): error TS1038: A 'declare' modifier cannot be used in an already ambient context. ==== tests/cases/conformance/parser/ecmascript5/ModuleDeclarations/parserModuleDeclaration4.d.ts (2 errors) ==== module M { ~~~~~~ -!!! error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +!!! error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. declare module M1 { ~~~~~~~ !!! error TS1038: A 'declare' modifier cannot be used in an already ambient context. diff --git a/tests/baselines/reference/parserVariableStatement1.d.errors.txt b/tests/baselines/reference/parserVariableStatement1.d.errors.txt index eb6f799df74ab..ade6a2ea338af 100644 --- a/tests/baselines/reference/parserVariableStatement1.d.errors.txt +++ b/tests/baselines/reference/parserVariableStatement1.d.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserVariableStatement1.d.ts(1,1): error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +tests/cases/conformance/parser/ecmascript5/Statements/parserVariableStatement1.d.ts(1,1): error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. tests/cases/conformance/parser/ecmascript5/Statements/parserVariableStatement1.d.ts(1,9): error TS1039: Initializers are not allowed in ambient contexts. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserVariableStatement1.d.ts (2 errors) ==== var v = 1; ~~~ -!!! error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +!!! error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. ~ !!! error TS1039: Initializers are not allowed in ambient contexts. \ No newline at end of file diff --git a/tests/baselines/reference/parserVariableStatement2.d.errors.txt b/tests/baselines/reference/parserVariableStatement2.d.errors.txt index c0cdb0e2ac4e2..fafb31d399963 100644 --- a/tests/baselines/reference/parserVariableStatement2.d.errors.txt +++ b/tests/baselines/reference/parserVariableStatement2.d.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/parser/ecmascript5/Statements/parserVariableStatement2.d.ts(1,1): error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. +tests/cases/conformance/parser/ecmascript5/Statements/parserVariableStatement2.d.ts(1,1): error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. ==== tests/cases/conformance/parser/ecmascript5/Statements/parserVariableStatement2.d.ts (1 errors) ==== var v; ~~~ -!!! error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file. \ No newline at end of file +!!! error TS1046: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. \ No newline at end of file From 9168bd4845a15b21f22ac3bd5011ad1364742208 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 25 Apr 2019 13:25:48 -0700 Subject: [PATCH 19/33] Simplify hasExportDeclarations (#27846) --- src/compiler/binder.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index ad02d84a35bdd..96db98d337a73 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1625,15 +1625,8 @@ namespace ts { } function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean { - const body = node.kind === SyntaxKind.SourceFile ? node : node.body; - if (body && (body.kind === SyntaxKind.SourceFile || body.kind === SyntaxKind.ModuleBlock)) { - for (const stat of (body).statements) { - if (stat.kind === SyntaxKind.ExportDeclaration || stat.kind === SyntaxKind.ExportAssignment) { - return true; - } - } - } - return false; + const body = isSourceFile(node) ? node : tryCast(node.body, isModuleBlock); + return !!body && body.statements.some(s => isExportDeclaration(s) || isExportAssignment(s)); } function setExportContextFlag(node: ModuleDeclaration | SourceFile) { From dc7c9bad3d7123bd2420405d95e302f45eda79ab Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 25 Apr 2019 13:26:19 -0700 Subject: [PATCH 20/33] Avoid eagerly computing test payload (#27851) --- src/testRunner/compilerRunner.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index c55cd1aa5117a..76c7c728aa19a 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -5,7 +5,7 @@ const enum CompilerTestType { } interface CompilerFileBasedTest extends Harness.FileBasedTest { - payload?: Harness.TestCaseParser.TestCaseContent; + readonly content?: string; } class CompilerBaselineRunner extends RunnerBase { @@ -74,7 +74,14 @@ class CompilerBaselineRunner extends RunnerBase { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Everything declared here should be cleared out in the "after" callback. let compilerTest!: CompilerTest; - before(() => { compilerTest = new CompilerTest(fileName, test && test.payload, configuration); }); + before(() => { + let payload; + if (test && test.content) { + const rootDir = test.file.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(test.file) + "/"; + payload = Harness.TestCaseParser.makeUnitsFromTest(test.content, test.file, rootDir); + } + compilerTest = new CompilerTest(fileName, payload, configuration); + }); it(`Correct errors for ${fileName}`, () => { compilerTest.verifyDiagnostics(); }); it(`Correct module resolution tracing for ${fileName}`, () => { compilerTest.verifyModuleResolution(); }); it(`Correct sourcemap content for ${fileName}`, () => { compilerTest.verifySourceMapRecord(); }); @@ -189,11 +196,9 @@ class CompilerTest { public static getConfigurations(file: string): CompilerFileBasedTest { // also see `parseCompilerTestConfigurations` in tests/webTestServer.ts const content = Harness.IO.readFile(file)!; - const rootDir = file.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(file) + "/"; - const payload = Harness.TestCaseParser.makeUnitsFromTest(content, file, rootDir); const settings = Harness.TestCaseParser.extractCompilerSettings(content); const configurations = Harness.getFileBasedTestConfigurations(settings, /*varyBy*/ ["module", "target"]); - return { file, payload, configurations }; + return { file, configurations, content }; } public verifyDiagnostics() { From b45df892a88ab751c4d2289b1e585eee9ad3d632 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Thu, 25 Apr 2019 22:33:49 +0200 Subject: [PATCH 21/33] emit error on destructuring of rest property (#29609) Fixes: #26005 --- src/compiler/checker.ts | 7 +++++ .../restPropertyWithBindingPattern.errors.txt | 28 +++++++++++++++++ .../restPropertyWithBindingPattern.js | 21 +++++++++++++ .../restPropertyWithBindingPattern.symbols | 6 ++++ .../restPropertyWithBindingPattern.types | 31 +++++++++++++++++++ .../restPropertyWithBindingPattern.ts | 4 +++ 6 files changed, 97 insertions(+) create mode 100644 tests/baselines/reference/restPropertyWithBindingPattern.errors.txt create mode 100644 tests/baselines/reference/restPropertyWithBindingPattern.js create mode 100644 tests/baselines/reference/restPropertyWithBindingPattern.symbols create mode 100644 tests/baselines/reference/restPropertyWithBindingPattern.types create mode 100644 tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9020d9e47dfd9..0c4d9e3aa71df 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31186,6 +31186,13 @@ namespace ts { for (const prop of node.properties) { if (prop.kind === SyntaxKind.SpreadAssignment) { + if (inDestructuring) { + // a rest property cannot be destructured any further + const expression = skipParentheses(prop.expression); + if (isArrayLiteralExpression(expression) || isObjectLiteralExpression(expression)) { + return grammarErrorOnNode(prop.expression, Diagnostics.A_rest_element_cannot_contain_a_binding_pattern); + } + } continue; } const name = prop.name; diff --git a/tests/baselines/reference/restPropertyWithBindingPattern.errors.txt b/tests/baselines/reference/restPropertyWithBindingPattern.errors.txt new file mode 100644 index 0000000000000..7ad0cac9ce3bc --- /dev/null +++ b/tests/baselines/reference/restPropertyWithBindingPattern.errors.txt @@ -0,0 +1,28 @@ +tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts(1,6): error TS2501: A rest element cannot contain a binding pattern. +tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts(2,6): error TS2501: A rest element cannot contain a binding pattern. +tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts(2,6): error TS2701: The target of an object rest assignment must be a variable or a property access. +tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts(3,6): error TS2461: Type '{}' is not an array type. +tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts(3,6): error TS2501: A rest element cannot contain a binding pattern. +tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts(4,6): error TS2501: A rest element cannot contain a binding pattern. +tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts(4,6): error TS2701: The target of an object rest assignment must be a variable or a property access. + + +==== tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts (7 errors) ==== + ({...{}} = {}); + ~~ +!!! error TS2501: A rest element cannot contain a binding pattern. + ({...({})} = {}); + ~~~~ +!!! error TS2501: A rest element cannot contain a binding pattern. + ~~~~ +!!! error TS2701: The target of an object rest assignment must be a variable or a property access. + ({...[]} = {}); + ~~ +!!! error TS2461: Type '{}' is not an array type. + ~~ +!!! error TS2501: A rest element cannot contain a binding pattern. + ({...([])} = {}); + ~~~~ +!!! error TS2501: A rest element cannot contain a binding pattern. + ~~~~ +!!! error TS2701: The target of an object rest assignment must be a variable or a property access. \ No newline at end of file diff --git a/tests/baselines/reference/restPropertyWithBindingPattern.js b/tests/baselines/reference/restPropertyWithBindingPattern.js new file mode 100644 index 0000000000000..c4a4795d6827b --- /dev/null +++ b/tests/baselines/reference/restPropertyWithBindingPattern.js @@ -0,0 +1,21 @@ +//// [restPropertyWithBindingPattern.ts] +({...{}} = {}); +({...({})} = {}); +({...[]} = {}); +({...([])} = {}); + +//// [restPropertyWithBindingPattern.js] +var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) + t[p[i]] = s[p[i]]; + return t; +}; +var _a, _b; +(_a = __rest({}, [])); +(({}) = __rest({}, [])); +(_b = __rest({}, [])); +(([]) = __rest({}, [])); diff --git a/tests/baselines/reference/restPropertyWithBindingPattern.symbols b/tests/baselines/reference/restPropertyWithBindingPattern.symbols new file mode 100644 index 0000000000000..79b4b6745e3b4 --- /dev/null +++ b/tests/baselines/reference/restPropertyWithBindingPattern.symbols @@ -0,0 +1,6 @@ +=== tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts === +({...{}} = {}); +No type information for this code.({...({})} = {}); +No type information for this code.({...[]} = {}); +No type information for this code.({...([])} = {}); +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/restPropertyWithBindingPattern.types b/tests/baselines/reference/restPropertyWithBindingPattern.types new file mode 100644 index 0000000000000..0cf290c792a4e --- /dev/null +++ b/tests/baselines/reference/restPropertyWithBindingPattern.types @@ -0,0 +1,31 @@ +=== tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts === +({...{}} = {}); +>({...{}} = {}) : {} +>{...{}} = {} : {} +>{...{}} : {} +>{} : {} +>{} : {} + +({...({})} = {}); +>({...({})} = {}) : {} +>{...({})} = {} : {} +>{...({})} : {} +>({}) : {} +>{} : {} +>{} : {} + +({...[]} = {}); +>({...[]} = {}) : {} +>{...[]} = {} : {} +>{...[]} : { [n: number]: undefined; length: number; toString(): string; toLocaleString(): string; pop(): undefined; push(...items: undefined[]): number; concat(...items: ConcatArray[]): undefined[]; concat(...items: ConcatArray[]): undefined[]; join(separator?: string): string; reverse(): undefined[]; shift(): undefined; slice(start?: number, end?: number): undefined[]; sort(compareFn?: (a: undefined, b: undefined) => number): undefined[]; splice(start: number, deleteCount?: number): undefined[]; splice(start: number, deleteCount: number, ...items: undefined[]): undefined[]; unshift(...items: undefined[]): number; indexOf(searchElement: undefined, fromIndex?: number): number; lastIndexOf(searchElement: undefined, fromIndex?: number): number; every(callbackfn: (value: undefined, index: number, array: undefined[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: undefined, index: number, array: undefined[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: undefined, index: number, array: undefined[]) => void, thisArg?: any): void; map(callbackfn: (value: undefined, index: number, array: undefined[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => any, thisArg?: any): undefined[]; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduce(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduceRight(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; } +>[] : undefined[] +>{} : {} + +({...([])} = {}); +>({...([])} = {}) : {} +>{...([])} = {} : {} +>{...([])} : { [n: number]: undefined; length: number; toString(): string; toLocaleString(): string; pop(): undefined; push(...items: undefined[]): number; concat(...items: ConcatArray[]): undefined[]; concat(...items: ConcatArray[]): undefined[]; join(separator?: string): string; reverse(): undefined[]; shift(): undefined; slice(start?: number, end?: number): undefined[]; sort(compareFn?: (a: undefined, b: undefined) => number): undefined[]; splice(start: number, deleteCount?: number): undefined[]; splice(start: number, deleteCount: number, ...items: undefined[]): undefined[]; unshift(...items: undefined[]): number; indexOf(searchElement: undefined, fromIndex?: number): number; lastIndexOf(searchElement: undefined, fromIndex?: number): number; every(callbackfn: (value: undefined, index: number, array: undefined[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: undefined, index: number, array: undefined[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: undefined, index: number, array: undefined[]) => void, thisArg?: any): void; map(callbackfn: (value: undefined, index: number, array: undefined[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: undefined, index: number, array: undefined[]) => any, thisArg?: any): undefined[]; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduce(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduceRight(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; } +>([]) : undefined[] +>[] : undefined[] +>{} : {} + diff --git a/tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts b/tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts new file mode 100644 index 0000000000000..fc7bd03561045 --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/restPropertyWithBindingPattern.ts @@ -0,0 +1,4 @@ +({...{}} = {}); +({...({})} = {}); +({...[]} = {}); +({...([])} = {}); \ No newline at end of file From 9bb837332774ae60356382f5ca5adce3d8137b78 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 25 Apr 2019 14:06:49 -0700 Subject: [PATCH 22/33] Accept API changes --- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5d5472e840592..93c49f699e75f 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3718,7 +3718,7 @@ declare namespace ts { get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; } - function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache; + function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions): ModuleResolutionCache; function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations | undefined; function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index e8e2bed3bb8f9..6a3c992bdb513 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3718,7 +3718,7 @@ declare namespace ts { get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; } - function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache; + function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string, options?: CompilerOptions): ModuleResolutionCache; function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations | undefined; function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; From 1a75d525fa5e87bc94af0403f036933e77717c26 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Fri, 26 Apr 2019 06:11:50 +0900 Subject: [PATCH 23/33] add ES2020 matchAll APIs (#30936) --- src/compiler/commandLineParser.ts | 4 ++++ src/compiler/types.ts | 3 ++- src/compiler/utilities.ts | 2 ++ src/lib/es2020.d.ts | 3 +++ src/lib/es2020.full.d.ts | 5 ++++ src/lib/es2020.string.d.ts | 10 ++++++++ src/lib/es2020.symbol.wellknown.d.ts | 19 +++++++++++++++ src/lib/libs.json | 4 ++++ src/server/protocol.ts | 3 +++ .../unittests/config/commandLineParsing.ts | 8 +++---- .../reference/api/tsserverlibrary.d.ts | 8 +++++-- tests/baselines/reference/api/typescript.d.ts | 5 ++-- tests/baselines/reference/regexMatchAll.js | 10 ++++++++ .../baselines/reference/regexMatchAll.symbols | 16 +++++++++++++ tests/baselines/reference/regexMatchAll.types | 24 +++++++++++++++++++ tests/baselines/reference/stringMatchAll.js | 10 ++++++++ .../reference/stringMatchAll.symbols | 15 ++++++++++++ .../baselines/reference/stringMatchAll.types | 22 +++++++++++++++++ tests/cases/compiler/regexMatchAll.ts | 5 ++++ tests/cases/compiler/stringMatchAll.ts | 5 ++++ 20 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 src/lib/es2020.d.ts create mode 100644 src/lib/es2020.full.d.ts create mode 100644 src/lib/es2020.string.d.ts create mode 100644 src/lib/es2020.symbol.wellknown.d.ts create mode 100644 tests/baselines/reference/regexMatchAll.js create mode 100644 tests/baselines/reference/regexMatchAll.symbols create mode 100644 tests/baselines/reference/regexMatchAll.types create mode 100644 tests/baselines/reference/stringMatchAll.js create mode 100644 tests/baselines/reference/stringMatchAll.symbols create mode 100644 tests/baselines/reference/stringMatchAll.types create mode 100644 tests/cases/compiler/regexMatchAll.ts create mode 100644 tests/cases/compiler/stringMatchAll.ts diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index e1a8d77b7675a..527217e860e6f 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -16,6 +16,7 @@ namespace ts { ["es2017", "lib.es2017.d.ts"], ["es2018", "lib.es2018.d.ts"], ["es2019", "lib.es2019.d.ts"], + ["es2020", "lib.es2020.d.ts"], ["esnext", "lib.esnext.d.ts"], // Host only ["dom", "lib.dom.d.ts"], @@ -46,6 +47,8 @@ namespace ts { ["es2019.array", "lib.es2019.array.d.ts"], ["es2019.string", "lib.es2019.string.d.ts"], ["es2019.symbol", "lib.es2019.symbol.d.ts"], + ["es2020.string", "lib.es2020.string.d.ts"], + ["es2020.symbol.wellknown", "lib.es2020.symbol.wellknown.d.ts"], ["esnext.array", "lib.es2019.array.d.ts"], ["esnext.symbol", "lib.es2019.symbol.d.ts"], ["esnext.asynciterable", "lib.es2018.asynciterable.d.ts"], @@ -210,6 +213,7 @@ namespace ts { es2017: ScriptTarget.ES2017, es2018: ScriptTarget.ES2018, es2019: ScriptTarget.ES2019, + es2020: ScriptTarget.ES2020, esnext: ScriptTarget.ESNext, }), affectsSourceFile: true, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b421efa19e0d8..62d0f27a6981b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4756,7 +4756,8 @@ namespace ts { ES2017 = 4, ES2018 = 5, ES2019 = 6, - ESNext = 7, + ES2020 = 7, + ESNext = 8, JSON = 100, Latest = ESNext, } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7deb2c823cdc1..76fb001de0dd9 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4677,6 +4677,8 @@ namespace ts { switch (options.target) { case ScriptTarget.ESNext: return "lib.esnext.full.d.ts"; + case ScriptTarget.ES2020: + return "lib.es2020.full.d.ts"; case ScriptTarget.ES2019: return "lib.es2019.full.d.ts"; case ScriptTarget.ES2018: diff --git a/src/lib/es2020.d.ts b/src/lib/es2020.d.ts new file mode 100644 index 0000000000000..fb55d987ebb5e --- /dev/null +++ b/src/lib/es2020.d.ts @@ -0,0 +1,3 @@ +/// +/// +/// diff --git a/src/lib/es2020.full.d.ts b/src/lib/es2020.full.d.ts new file mode 100644 index 0000000000000..0d4b6d45d55ad --- /dev/null +++ b/src/lib/es2020.full.d.ts @@ -0,0 +1,5 @@ +/// +/// +/// +/// +/// diff --git a/src/lib/es2020.string.d.ts b/src/lib/es2020.string.d.ts new file mode 100644 index 0000000000000..335a0ac000577 --- /dev/null +++ b/src/lib/es2020.string.d.ts @@ -0,0 +1,10 @@ +/// + +interface String { + /** + * Matches a string with a regular expression, and returns an iterable of matches + * containing the results of that search. + * @param regexp A variable name or string literal containing the regular expression pattern and flags. + */ + matchAll(regexp: RegExp): IterableIterator; +} diff --git a/src/lib/es2020.symbol.wellknown.d.ts b/src/lib/es2020.symbol.wellknown.d.ts new file mode 100644 index 0000000000000..76e377e0be270 --- /dev/null +++ b/src/lib/es2020.symbol.wellknown.d.ts @@ -0,0 +1,19 @@ +/// +/// + +interface SymbolConstructor { + /** + * A regular expression method that matches the regular expression against a string. Called + * by the String.prototype.matchAll method. + */ + readonly matchAll: symbol; +} + +interface RegExp { + /** + * Matches a string with this regular expression, and returns an iterable of matches + * containing the results of that search. + * @param string A string to search within. + */ + [Symbol.matchAll](str: string): IterableIterator; +} diff --git a/src/lib/libs.json b/src/lib/libs.json index fa5f4060acd6a..74611a938609c 100644 --- a/src/lib/libs.json +++ b/src/lib/libs.json @@ -7,6 +7,7 @@ "es2017", "es2018", "es2019", + "es2020", "esnext", // Host only "dom.generated", @@ -37,6 +38,8 @@ "es2019.array", "es2019.string", "es2019.symbol", + "es2020.string", + "es2020.symbol.wellknown", "esnext.bigint", "esnext.intl", // Default libraries @@ -46,6 +49,7 @@ "es2017.full", "es2018.full", "es2019.full", + "es2020.full", "esnext.full" ], "paths": { diff --git a/src/server/protocol.ts b/src/server/protocol.ts index e5580874369e6..3da890a766ff7 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -3046,6 +3046,9 @@ namespace ts.server.protocol { ES2015 = "ES2015", ES2016 = "ES2016", ES2017 = "ES2017", + ES2018 = "ES2018", + ES2019 = "ES2019", + ES2020 = "ES2020", ESNext = "ESNext" } } diff --git a/src/testRunner/unittests/config/commandLineParsing.ts b/src/testRunner/unittests/config/commandLineParsing.ts index ccb2378c644a8..450b27e01ed4f 100644 --- a/src/testRunner/unittests/config/commandLineParsing.ts +++ b/src/testRunner/unittests/config/commandLineParsing.ts @@ -57,7 +57,7 @@ namespace ts { assertParseResult(["--lib", "es5,invalidOption", "0.ts"], { errors: [{ - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.string', 'es2019.symbol', 'esnext.array', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.bigint'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.string', 'es2019.symbol', 'es2020.string', 'es2020.symbol.wellknown', 'esnext.array', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.bigint'.", category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, @@ -161,7 +161,7 @@ namespace ts { start: undefined, length: undefined, }, { - messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'esnext'.", + messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'esnext'.", category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, @@ -259,7 +259,7 @@ namespace ts { assertParseResult(["--lib", "es5,", "es7", "0.ts"], { errors: [{ - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.string', 'es2019.symbol', 'esnext.array', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.bigint'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.string', 'es2019.symbol', 'es2020.string', 'es2020.symbol.wellknown', 'esnext.array', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.bigint'.", category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, @@ -278,7 +278,7 @@ namespace ts { assertParseResult(["--lib", "es5, ", "es7", "0.ts"], { errors: [{ - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.string', 'es2019.symbol', 'esnext.array', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.bigint'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.string', 'es2019.symbol', 'es2020.string', 'es2020.symbol.wellknown', 'esnext.array', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.bigint'.", category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5d5472e840592..621b9149a68b4 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2625,9 +2625,10 @@ declare namespace ts { ES2017 = 4, ES2018 = 5, ES2019 = 6, - ESNext = 7, + ES2020 = 7, + ESNext = 8, JSON = 100, - Latest = 7 + Latest = 8 } enum LanguageVariant { Standard = 0, @@ -8127,6 +8128,9 @@ declare namespace ts.server.protocol { ES2015 = "ES2015", ES2016 = "ES2016", ES2017 = "ES2017", + ES2018 = "ES2018", + ES2019 = "ES2019", + ES2020 = "ES2020", ESNext = "ESNext" } } diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index e8e2bed3bb8f9..643c68abe97ec 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2625,9 +2625,10 @@ declare namespace ts { ES2017 = 4, ES2018 = 5, ES2019 = 6, - ESNext = 7, + ES2020 = 7, + ESNext = 8, JSON = 100, - Latest = 7 + Latest = 8 } enum LanguageVariant { Standard = 0, diff --git a/tests/baselines/reference/regexMatchAll.js b/tests/baselines/reference/regexMatchAll.js new file mode 100644 index 0000000000000..5b169725ae27e --- /dev/null +++ b/tests/baselines/reference/regexMatchAll.js @@ -0,0 +1,10 @@ +//// [regexMatchAll.ts] +const matches = /\w/g[Symbol.matchAll]("matchAll"); +const array = [...matches]; +const { index, input } = array[0]; + + +//// [regexMatchAll.js] +const matches = /\w/g[Symbol.matchAll]("matchAll"); +const array = [...matches]; +const { index, input } = array[0]; diff --git a/tests/baselines/reference/regexMatchAll.symbols b/tests/baselines/reference/regexMatchAll.symbols new file mode 100644 index 0000000000000..aa811a1f67614 --- /dev/null +++ b/tests/baselines/reference/regexMatchAll.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/regexMatchAll.ts === +const matches = /\w/g[Symbol.matchAll]("matchAll"); +>matches : Symbol(matches, Decl(regexMatchAll.ts, 0, 5)) +>Symbol.matchAll : Symbol(SymbolConstructor.matchAll, Decl(lib.es2020.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>matchAll : Symbol(SymbolConstructor.matchAll, Decl(lib.es2020.symbol.wellknown.d.ts, --, --)) + +const array = [...matches]; +>array : Symbol(array, Decl(regexMatchAll.ts, 1, 5)) +>matches : Symbol(matches, Decl(regexMatchAll.ts, 0, 5)) + +const { index, input } = array[0]; +>index : Symbol(index, Decl(regexMatchAll.ts, 2, 7)) +>input : Symbol(input, Decl(regexMatchAll.ts, 2, 14)) +>array : Symbol(array, Decl(regexMatchAll.ts, 1, 5)) + diff --git a/tests/baselines/reference/regexMatchAll.types b/tests/baselines/reference/regexMatchAll.types new file mode 100644 index 0000000000000..a109cdc46116b --- /dev/null +++ b/tests/baselines/reference/regexMatchAll.types @@ -0,0 +1,24 @@ +=== tests/cases/compiler/regexMatchAll.ts === +const matches = /\w/g[Symbol.matchAll]("matchAll"); +>matches : IterableIterator +>/\w/g[Symbol.matchAll]("matchAll") : IterableIterator +>/\w/g[Symbol.matchAll] : (str: string) => IterableIterator +>/\w/g : RegExp +>Symbol.matchAll : symbol +>Symbol : SymbolConstructor +>matchAll : symbol +>"matchAll" : "matchAll" + +const array = [...matches]; +>array : RegExpMatchArray[] +>[...matches] : RegExpMatchArray[] +>...matches : RegExpMatchArray +>matches : IterableIterator + +const { index, input } = array[0]; +>index : number +>input : string +>array[0] : RegExpMatchArray +>array : RegExpMatchArray[] +>0 : 0 + diff --git a/tests/baselines/reference/stringMatchAll.js b/tests/baselines/reference/stringMatchAll.js new file mode 100644 index 0000000000000..fbb3c1174b731 --- /dev/null +++ b/tests/baselines/reference/stringMatchAll.js @@ -0,0 +1,10 @@ +//// [stringMatchAll.ts] +const matches = "matchAll".matchAll(/\w/g); +const array = [...matches]; +const { index, input } = array[0]; + + +//// [stringMatchAll.js] +const matches = "matchAll".matchAll(/\w/g); +const array = [...matches]; +const { index, input } = array[0]; diff --git a/tests/baselines/reference/stringMatchAll.symbols b/tests/baselines/reference/stringMatchAll.symbols new file mode 100644 index 0000000000000..91ad541338ad4 --- /dev/null +++ b/tests/baselines/reference/stringMatchAll.symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/stringMatchAll.ts === +const matches = "matchAll".matchAll(/\w/g); +>matches : Symbol(matches, Decl(stringMatchAll.ts, 0, 5)) +>"matchAll".matchAll : Symbol(String.matchAll, Decl(lib.es2020.string.d.ts, --, --)) +>matchAll : Symbol(String.matchAll, Decl(lib.es2020.string.d.ts, --, --)) + +const array = [...matches]; +>array : Symbol(array, Decl(stringMatchAll.ts, 1, 5)) +>matches : Symbol(matches, Decl(stringMatchAll.ts, 0, 5)) + +const { index, input } = array[0]; +>index : Symbol(index, Decl(stringMatchAll.ts, 2, 7)) +>input : Symbol(input, Decl(stringMatchAll.ts, 2, 14)) +>array : Symbol(array, Decl(stringMatchAll.ts, 1, 5)) + diff --git a/tests/baselines/reference/stringMatchAll.types b/tests/baselines/reference/stringMatchAll.types new file mode 100644 index 0000000000000..d63de9540b5f6 --- /dev/null +++ b/tests/baselines/reference/stringMatchAll.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/stringMatchAll.ts === +const matches = "matchAll".matchAll(/\w/g); +>matches : IterableIterator +>"matchAll".matchAll(/\w/g) : IterableIterator +>"matchAll".matchAll : (regexp: RegExp) => IterableIterator +>"matchAll" : "matchAll" +>matchAll : (regexp: RegExp) => IterableIterator +>/\w/g : RegExp + +const array = [...matches]; +>array : RegExpMatchArray[] +>[...matches] : RegExpMatchArray[] +>...matches : RegExpMatchArray +>matches : IterableIterator + +const { index, input } = array[0]; +>index : number +>input : string +>array[0] : RegExpMatchArray +>array : RegExpMatchArray[] +>0 : 0 + diff --git a/tests/cases/compiler/regexMatchAll.ts b/tests/cases/compiler/regexMatchAll.ts new file mode 100644 index 0000000000000..b18ab9fd2968b --- /dev/null +++ b/tests/cases/compiler/regexMatchAll.ts @@ -0,0 +1,5 @@ +// @target: es2020 + +const matches = /\w/g[Symbol.matchAll]("matchAll"); +const array = [...matches]; +const { index, input } = array[0]; diff --git a/tests/cases/compiler/stringMatchAll.ts b/tests/cases/compiler/stringMatchAll.ts new file mode 100644 index 0000000000000..9b2ae1a9d641f --- /dev/null +++ b/tests/cases/compiler/stringMatchAll.ts @@ -0,0 +1,5 @@ +// @target: es2020 + +const matches = "matchAll".matchAll(/\w/g); +const array = [...matches]; +const { index, input } = array[0]; From 867c992021c08b618c1e06c868bf8c4ca51ece03 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 25 Apr 2019 14:45:44 -0700 Subject: [PATCH 24/33] Update pull_request_template.md --- .github/pull_request_template.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 7a0f12ce7ceaf..da9561b8eb413 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,8 +1,8 @@ Fixes # - From b8e3c41ee1fc228717c9ed672b5c838cb74dc3cb Mon Sep 17 00:00:00 2001 From: Wenlu Wang Date: Thu, 25 Apr 2019 16:53:06 -0500 Subject: [PATCH 25/33] fix jsdoc iterator on expression of export assignment (#30558) --- src/compiler/utilities.ts | 1 + .../reference/exportDefaultWithJSDoc1.symbols | 15 +++++++++++++++ .../reference/exportDefaultWithJSDoc1.types | 19 +++++++++++++++++++ .../reference/exportDefaultWithJSDoc2.symbols | 15 +++++++++++++++ .../reference/exportDefaultWithJSDoc2.types | 19 +++++++++++++++++++ .../cases/compiler/exportDefaultWithJSDoc1.ts | 16 ++++++++++++++++ .../cases/compiler/exportDefaultWithJSDoc2.ts | 16 ++++++++++++++++ 7 files changed, 101 insertions(+) create mode 100644 tests/baselines/reference/exportDefaultWithJSDoc1.symbols create mode 100644 tests/baselines/reference/exportDefaultWithJSDoc1.types create mode 100644 tests/baselines/reference/exportDefaultWithJSDoc2.symbols create mode 100644 tests/baselines/reference/exportDefaultWithJSDoc2.types create mode 100644 tests/cases/compiler/exportDefaultWithJSDoc1.ts create mode 100644 tests/cases/compiler/exportDefaultWithJSDoc2.ts diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 76fb001de0dd9..e7cf9a6a62a13 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2221,6 +2221,7 @@ namespace ts { function getNextJSDocCommentLocation(node: Node) { const parent = node.parent; if (parent.kind === SyntaxKind.PropertyAssignment || + parent.kind === SyntaxKind.ExportAssignment || parent.kind === SyntaxKind.PropertyDeclaration || parent.kind === SyntaxKind.ExpressionStatement && node.kind === SyntaxKind.PropertyAccessExpression || getNestedModuleDeclaration(parent) || diff --git a/tests/baselines/reference/exportDefaultWithJSDoc1.symbols b/tests/baselines/reference/exportDefaultWithJSDoc1.symbols new file mode 100644 index 0000000000000..bad38b845bb09 --- /dev/null +++ b/tests/baselines/reference/exportDefaultWithJSDoc1.symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/a.js === +/** +No type information for this code. * A number, or a string containing a number. +No type information for this code. * @typedef {(number|string)} NumberLike +No type information for this code. */ +No type information for this code. +No type information for this code./** @type {NumberLike[]} */export default ([ ]); +No type information for this code. +No type information for this code.=== tests/cases/compiler/b.ts === +import A from './a' +>A : Symbol(A, Decl(b.ts, 0, 6)) + +A[0] +>A : Symbol(A, Decl(b.ts, 0, 6)) + diff --git a/tests/baselines/reference/exportDefaultWithJSDoc1.types b/tests/baselines/reference/exportDefaultWithJSDoc1.types new file mode 100644 index 0000000000000..5e82e37b33b2a --- /dev/null +++ b/tests/baselines/reference/exportDefaultWithJSDoc1.types @@ -0,0 +1,19 @@ +=== tests/cases/compiler/a.js === +/** + * A number, or a string containing a number. + * @typedef {(number|string)} NumberLike + */ + +/** @type {NumberLike[]} */export default ([ ]); +>([ ]) : (string | number)[] +>[ ] : undefined[] + +=== tests/cases/compiler/b.ts === +import A from './a' +>A : (string | number)[] + +A[0] +>A[0] : string | number +>A : (string | number)[] +>0 : 0 + diff --git a/tests/baselines/reference/exportDefaultWithJSDoc2.symbols b/tests/baselines/reference/exportDefaultWithJSDoc2.symbols new file mode 100644 index 0000000000000..ff3e74a3fbe94 --- /dev/null +++ b/tests/baselines/reference/exportDefaultWithJSDoc2.symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/a.js === +/** +No type information for this code. * A number, or a string containing a number. +No type information for this code. * @typedef {(number|string)} NumberLike +No type information for this code. */ +No type information for this code. +No type information for this code.export default /** @type {NumberLike[]} */([ ]); +No type information for this code. +No type information for this code.=== tests/cases/compiler/b.ts === +import A from './a' +>A : Symbol(A, Decl(b.ts, 0, 6)) + +A[0] +>A : Symbol(A, Decl(b.ts, 0, 6)) + diff --git a/tests/baselines/reference/exportDefaultWithJSDoc2.types b/tests/baselines/reference/exportDefaultWithJSDoc2.types new file mode 100644 index 0000000000000..0fd9f022a7321 --- /dev/null +++ b/tests/baselines/reference/exportDefaultWithJSDoc2.types @@ -0,0 +1,19 @@ +=== tests/cases/compiler/a.js === +/** + * A number, or a string containing a number. + * @typedef {(number|string)} NumberLike + */ + +export default /** @type {NumberLike[]} */([ ]); +>([ ]) : (string | number)[] +>[ ] : undefined[] + +=== tests/cases/compiler/b.ts === +import A from './a' +>A : (string | number)[] + +A[0] +>A[0] : string | number +>A : (string | number)[] +>0 : 0 + diff --git a/tests/cases/compiler/exportDefaultWithJSDoc1.ts b/tests/cases/compiler/exportDefaultWithJSDoc1.ts new file mode 100644 index 0000000000000..2140ccc8aa164 --- /dev/null +++ b/tests/cases/compiler/exportDefaultWithJSDoc1.ts @@ -0,0 +1,16 @@ + +// @allowJs: true +// @checkJs: true +// @noEmit: true + +/** + * A number, or a string containing a number. + * @typedef {(number|string)} NumberLike + */ + +// @Filename: a.js +/** @type {NumberLike[]} */export default ([ ]); + +// @Filename: b.ts +import A from './a' +A[0] \ No newline at end of file diff --git a/tests/cases/compiler/exportDefaultWithJSDoc2.ts b/tests/cases/compiler/exportDefaultWithJSDoc2.ts new file mode 100644 index 0000000000000..1b14248bfa668 --- /dev/null +++ b/tests/cases/compiler/exportDefaultWithJSDoc2.ts @@ -0,0 +1,16 @@ + +// @allowJs: true +// @checkJs: true +// @noEmit: true + +/** + * A number, or a string containing a number. + * @typedef {(number|string)} NumberLike + */ + +// @Filename: a.js +export default /** @type {NumberLike[]} */([ ]); + +// @Filename: b.ts +import A from './a' +A[0] \ No newline at end of file From 5b79b942e8114b4f10ecd7c61c159ef4f3bdacbb Mon Sep 17 00:00:00 2001 From: amaksimovich2 Date: Fri, 26 Apr 2019 00:55:04 +0300 Subject: [PATCH 26/33] =?UTF-8?q?add=20action=20for=20enabling=20experimen?= =?UTF-8?q?talDescorators=20option=20in=20user=20config=E2=80=A6=20(#30484?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add action for enabling experimentalDescorators option in user config file, change error message for this case #29035 * add missing changes in tests * Add "experimental decorators" tests for jsconfig file --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- src/compiler/program.ts | 2 +- .../fixEnableExperimentalDecorators.ts | 13 ++++++--- .../reference/decoratorInJsFile1.errors.txt | 4 +-- .../reference/generatorTypeCheck39.errors.txt | 4 +-- .../reference/generatorTypeCheck59.errors.txt | 4 +-- .../reference/generatorTypeCheck61.errors.txt | 4 +-- ...corators_blankCompilerOptionsInJsconfig.ts | 26 ++++++++++++++++++ ...orators_blankCompilerOptionsInTsconfig.ts} | 0 ...ors_disabledInCompilerOptionsInJsconfig.ts | 27 +++++++++++++++++++ ...rs_disabledInCompilerOptionsInTsconfig.ts} | 0 ...rators_missingCompilerOptionsInJsconfig.ts | 22 +++++++++++++++ ...ators_missingCompilerOptionsInTsconfig.ts} | 0 14 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInJsconfig.ts rename tests/cases/fourslash/{codefixEnableExperimentalDecorators_blankCompilerOptions.ts => codefixEnableExperimentalDecorators_blankCompilerOptionsInTsconfig.ts} (100%) create mode 100644 tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptionsInJsconfig.ts rename tests/cases/fourslash/{codefixEnableExperimentalDecorators_disabledInCompilerOptions.ts => codefixEnableExperimentalDecorators_disabledInCompilerOptionsInTsconfig.ts} (100%) create mode 100644 tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInJsconfig.ts rename tests/cases/fourslash/{codefixEnableExperimentalDecorators_missingCompilerOptions.ts => codefixEnableExperimentalDecorators_missingCompilerOptionsInTsconfig.ts} (100%) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0c4d9e3aa71df..7431d2118426e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -25636,7 +25636,7 @@ namespace ts { } if (!compilerOptions.experimentalDecorators) { - error(node, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning); + error(node, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_in_your_tsconfig_or_jsconfig_to_remove_this_warning); } const firstDecorator = node.decorators[0]; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index befff38aee16b..45ec2a9ad427a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -691,7 +691,7 @@ "category": "Error", "code": 1218 }, - "Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning.": { + "Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning.": { "category": "Error", "code": 1219 }, diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 4f50aa3ab1f59..9b3014390a330 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1816,7 +1816,7 @@ namespace ts { function walkArray(nodes: NodeArray) { if (parent.decorators === nodes && !options.experimentalDecorators) { - diagnostics.push(createDiagnosticForNode(parent, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning)); + diagnostics.push(createDiagnosticForNode(parent, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_in_your_tsconfig_or_jsconfig_to_remove_this_warning)); } switch (parent.kind) { diff --git a/src/services/codefixes/fixEnableExperimentalDecorators.ts b/src/services/codefixes/fixEnableExperimentalDecorators.ts index 8aeefe48a47b5..8ab1c2769104d 100644 --- a/src/services/codefixes/fixEnableExperimentalDecorators.ts +++ b/src/services/codefixes/fixEnableExperimentalDecorators.ts @@ -2,7 +2,7 @@ namespace ts.codefix { const fixId = "enableExperimentalDecorators"; const errorCodes = [ - Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning.code + Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_in_your_tsconfig_or_jsconfig_to_remove_this_warning.code ]; registerCodeFix({ errorCodes, @@ -12,13 +12,20 @@ namespace ts.codefix { return undefined; } - const changes = textChanges.ChangeTracker.with(context, changeTracker => makeChange(changeTracker, configFile)); + const changes = textChanges.ChangeTracker.with(context, changeTracker => doChange(changeTracker, configFile)); return [createCodeFixActionNoFixId(fixId, changes, Diagnostics.Enable_the_experimentalDecorators_option_in_your_configuration_file)]; }, fixIds: [fixId], + getAllCodeActions: context => codeFixAll(context, errorCodes, (changes) => { + const { configFile } = context.program.getCompilerOptions(); + if (configFile === undefined) { + return undefined; + } + doChange(changes, configFile); + }), }); - function makeChange(changeTracker: textChanges.ChangeTracker, configFile: TsConfigSourceFile) { + function doChange(changeTracker: textChanges.ChangeTracker, configFile: TsConfigSourceFile) { setJsonCompilerOptionValue(changeTracker, configFile, "experimentalDecorators", createTrue()); } } diff --git a/tests/baselines/reference/decoratorInJsFile1.errors.txt b/tests/baselines/reference/decoratorInJsFile1.errors.txt index d660b6b28df1f..9cb55bd201692 100644 --- a/tests/baselines/reference/decoratorInJsFile1.errors.txt +++ b/tests/baselines/reference/decoratorInJsFile1.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/a.js(2,7): error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning. +tests/cases/compiler/a.js(2,7): error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning. tests/cases/compiler/a.js(3,12): error TS8010: 'types' can only be used in a .ts file. @@ -6,7 +6,7 @@ tests/cases/compiler/a.js(3,12): error TS8010: 'types' can only be used in a .ts @SomeDecorator class SomeClass { ~~~~~~~~~ -!!! error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning. +!!! error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning. foo(x: number) { ~~~~~~ !!! error TS8010: 'types' can only be used in a .ts file. diff --git a/tests/baselines/reference/generatorTypeCheck39.errors.txt b/tests/baselines/reference/generatorTypeCheck39.errors.txt index aabb5a47a355d..fe0162233e09b 100644 --- a/tests/baselines/reference/generatorTypeCheck39.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck39.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(5,16): error TS1163: A 'yield' expression is only allowed in a generator body. -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(6,11): error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning. +tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(6,11): error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning. tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(7,13): error TS1163: A 'yield' expression is only allowed in a generator body. @@ -13,7 +13,7 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck39.ts(7,13): erro !!! error TS1163: A 'yield' expression is only allowed in a generator body. class C { ~ -!!! error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning. +!!! error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning. x = yield 0; ~~~~~ !!! error TS1163: A 'yield' expression is only allowed in a generator body. diff --git a/tests/baselines/reference/generatorTypeCheck59.errors.txt b/tests/baselines/reference/generatorTypeCheck59.errors.txt index cba90154701af..5cec6ac1f2460 100644 --- a/tests/baselines/reference/generatorTypeCheck59.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck59.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts(3,11): error TS1163: A 'yield' expression is only allowed in a generator body. -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts(4,9): error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning. +tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts(4,9): error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning. ==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts (2 errors) ==== @@ -10,6 +10,6 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts(4,9): error !!! error TS1163: A 'yield' expression is only allowed in a generator body. m() { } ~ -!!! error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning. +!!! error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning. }; } \ No newline at end of file diff --git a/tests/baselines/reference/generatorTypeCheck61.errors.txt b/tests/baselines/reference/generatorTypeCheck61.errors.txt index ccc99f7ffbd34..a80949e8876af 100644 --- a/tests/baselines/reference/generatorTypeCheck61.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck61.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(2,7): error TS1163: A 'yield' expression is only allowed in a generator body. -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(3,11): error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning. +tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(3,11): error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning. ==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts (2 errors) ==== @@ -9,5 +9,5 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(3,11): erro !!! error TS1163: A 'yield' expression is only allowed in a generator body. class C {}; ~ -!!! error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning. +!!! error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning. } \ No newline at end of file diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInJsconfig.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInJsconfig.ts new file mode 100644 index 0000000000000..f8dcbf75e4824 --- /dev/null +++ b/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInJsconfig.ts @@ -0,0 +1,26 @@ +/// + +// @Filename: /dir/a.ts +////declare const decorator: any; +////class A { +//// @decorator method() {}; +////}; + +// @Filename: /dir/jsconfig.json +////{ +//// "compilerOptions": { +//// } +////} + +goTo.file("/dir/a.ts"); +verify.codeFix({ + description: "Enable the 'experimentalDecorators' option in your configuration file", + newFileContent: { + "/dir/jsconfig.json": +`{ + "compilerOptions": { + "experimentalDecorators": true, + } +}`, + }, +}); diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptions.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInTsconfig.ts similarity index 100% rename from tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptions.ts rename to tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptionsInTsconfig.ts diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptionsInJsconfig.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptionsInJsconfig.ts new file mode 100644 index 0000000000000..2b0809fe8c8b5 --- /dev/null +++ b/tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptionsInJsconfig.ts @@ -0,0 +1,27 @@ +/// + +// @Filename: /dir/a.ts +////declare const decorator: any; +////class A { +//// @decorator method() {}; +////}; + +// @Filename: /dir/jsconfig.json +////{ +//// "compilerOptions": { +//// "experimentalDecorators": false, +//// } +////} + +goTo.file("/dir/a.ts"); +verify.codeFix({ + description: "Enable the 'experimentalDecorators' option in your configuration file", + newFileContent: { + "/dir/jsconfig.json": +`{ + "compilerOptions": { + "experimentalDecorators": true, + } +}`, + }, +}); diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptions.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptionsInTsconfig.ts similarity index 100% rename from tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptions.ts rename to tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptionsInTsconfig.ts diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInJsconfig.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInJsconfig.ts new file mode 100644 index 0000000000000..644fce3a35f56 --- /dev/null +++ b/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInJsconfig.ts @@ -0,0 +1,22 @@ +/// + +// @Filename: /dir/a.ts +////declare const decorator: any; +////class A { +//// @decorator method() {}; +////}; + +// @Filename: /dir/jsconfig.json +////{ +////} + +goTo.file("/dir/a.ts"); +verify.codeFix({ + description: "Enable the 'experimentalDecorators' option in your configuration file", + newFileContent: { + "/dir/jsconfig.json": +`{ + "compilerOptions": { "experimentalDecorators": true }, +}`, + }, +}); diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptions.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInTsconfig.ts similarity index 100% rename from tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptions.ts rename to tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptionsInTsconfig.ts From f9d12ed54b82fa896cfa66bfdfc8abb7a93ed1fa Mon Sep 17 00:00:00 2001 From: Max Heiber Date: Thu, 25 Apr 2019 23:31:03 +0100 Subject: [PATCH 27/33] fix 31012 allow noEmitOnError with isolatedModules (#34) (#31043) fix #31012 Since the purpose of isolatedModules: true is to do extra validation to ensure that separate compilation is safe Allowing emit in the presence of errors is compatible with that intention. Signed-off-by: Max Heiber --- src/compiler/program.ts | 4 ---- .../reference/isolatedModulesNoEmitOnError.errors.txt | 9 +++++---- .../reference/isolatedModulesNoEmitOnError.symbols | 4 ++-- .../reference/isolatedModulesNoEmitOnError.types | 5 +++-- tests/cases/compiler/isolatedModulesNoEmitOnError.ts | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 9b3014390a330..6b8f56d1daf35 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2707,10 +2707,6 @@ namespace ts { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, getEmitDeclarationOptionName(options), "isolatedModules"); } - if (options.noEmitOnError) { - createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmitOnError", "isolatedModules"); - } - if (options.out) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "isolatedModules"); } diff --git a/tests/baselines/reference/isolatedModulesNoEmitOnError.errors.txt b/tests/baselines/reference/isolatedModulesNoEmitOnError.errors.txt index 34ff251c16701..2ddfa178de239 100644 --- a/tests/baselines/reference/isolatedModulesNoEmitOnError.errors.txt +++ b/tests/baselines/reference/isolatedModulesNoEmitOnError.errors.txt @@ -1,6 +1,7 @@ -error TS5053: Option 'noEmitOnError' cannot be specified with option 'isolatedModules'. +tests/cases/compiler/file1.ts(1,14): error TS2322: Type '3' is not assignable to type 'string'. -!!! error TS5053: Option 'noEmitOnError' cannot be specified with option 'isolatedModules'. -==== tests/cases/compiler/file1.ts (0 errors) ==== - export var x; \ No newline at end of file +==== tests/cases/compiler/file1.ts (1 errors) ==== + export const x: string = 3; + ~ +!!! error TS2322: Type '3' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/isolatedModulesNoEmitOnError.symbols b/tests/baselines/reference/isolatedModulesNoEmitOnError.symbols index 625dbfbe699b8..67306c205a7ea 100644 --- a/tests/baselines/reference/isolatedModulesNoEmitOnError.symbols +++ b/tests/baselines/reference/isolatedModulesNoEmitOnError.symbols @@ -1,4 +1,4 @@ === tests/cases/compiler/file1.ts === -export var x; ->x : Symbol(x, Decl(file1.ts, 0, 10)) +export const x: string = 3; +>x : Symbol(x, Decl(file1.ts, 0, 12)) diff --git a/tests/baselines/reference/isolatedModulesNoEmitOnError.types b/tests/baselines/reference/isolatedModulesNoEmitOnError.types index 27dca700bb904..3a4f55b925cba 100644 --- a/tests/baselines/reference/isolatedModulesNoEmitOnError.types +++ b/tests/baselines/reference/isolatedModulesNoEmitOnError.types @@ -1,4 +1,5 @@ === tests/cases/compiler/file1.ts === -export var x; ->x : any +export const x: string = 3; +>x : string +>3 : 3 diff --git a/tests/cases/compiler/isolatedModulesNoEmitOnError.ts b/tests/cases/compiler/isolatedModulesNoEmitOnError.ts index ce3085dbc3b9f..46ab4efcb089c 100644 --- a/tests/cases/compiler/isolatedModulesNoEmitOnError.ts +++ b/tests/cases/compiler/isolatedModulesNoEmitOnError.ts @@ -3,4 +3,4 @@ // @target: es6 // @filename: file1.ts -export var x; \ No newline at end of file +export const x: string = 3; \ No newline at end of file From d865ea774af43b0e3563064edb7fa12a199be1ce Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Fri, 26 Apr 2019 00:43:43 +0200 Subject: [PATCH 28/33] resolveName: remove useless case (#28669) PropertySignature cannot occur in a class. The condition inside the clause required the parent to be a class, so it was never true. This removes the case clause and the part of the condition that is now useless. --- src/compiler/checker.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7431d2118426e..473b41ccec5e2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1409,15 +1409,14 @@ namespace ts { } break; case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: // TypeScript 1.0 spec (April 2014): 8.4.1 // Initializer expressions for instance member variables are evaluated in the scope // of the class constructor body but are not permitted to reference parameters or // local variables of the constructor. This effectively means that entities from outer scopes // by the same name as a constructor parameter or local variable are inaccessible // in initializer expressions for instance member variables. - if (isClassLike(location.parent) && !hasModifier(location, ModifierFlags.Static)) { - const ctor = findConstructorDeclaration(location.parent); + if (!hasModifier(location, ModifierFlags.Static)) { + const ctor = findConstructorDeclaration(location.parent as ClassLikeDeclaration); if (ctor && ctor.locals) { if (lookup(ctor.locals, name, meaning & SymbolFlags.Value)) { // Remember the property node, it will be used later to report appropriate error From 0949ad1130bc98718595d8001addb93bde7390dd Mon Sep 17 00:00:00 2001 From: Jack Williams Date: Fri, 26 Apr 2019 03:30:03 +0100 Subject: [PATCH 29/33] Fix #24991: Weaken narrowing for == (#29840) Spelling --- src/compiler/checker.ts | 31 +++- .../reference/narrowByEquality.errors.txt | 71 ++++++++++ tests/baselines/reference/narrowByEquality.js | 101 ++++++++++++++ .../reference/narrowByEquality.symbols | 113 +++++++++++++++ .../reference/narrowByEquality.types | 132 ++++++++++++++++++ tests/cases/compiler/narrowByEquality.ts | 59 ++++++++ 6 files changed, 506 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/narrowByEquality.errors.txt create mode 100644 tests/baselines/reference/narrowByEquality.js create mode 100644 tests/baselines/reference/narrowByEquality.symbols create mode 100644 tests/baselines/reference/narrowByEquality.types create mode 100644 tests/cases/compiler/narrowByEquality.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c7774d2d916e7..913d7f3b2a91a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14227,6 +14227,32 @@ namespace ts { return strictNullChecks ? getGlobalNonNullableTypeInstantiation(type) : type; } + + /** + * Is source potentially coercible to target type under `==`. + * Assumes that `source` is a constituent of a union, hence + * the boolean literal flag on the LHS, but not on the RHS. + * + * This does not fully replicate the semantics of `==`. The + * intention is to catch cases that are clearly not right. + * + * Comparing (string | number) to number should not remove the + * string element. + * + * Comparing (string | number) to 1 will remove the string + * element, though this is not sound. This is a pragmatic + * choice. + * + * @see narrowTypeByEquality + * + * @param source + * @param target + */ + function isCoercibleUnderDoubleEquals(source: Type, target: Type): boolean { + return ((source.flags & (TypeFlags.Number | TypeFlags.String | TypeFlags.BooleanLiteral)) !== 0) + && ((target.flags & (TypeFlags.Number | TypeFlags.String | TypeFlags.Boolean)) !== 0); + } + /** * Return true if type was inferred from an object literal, written as an object type literal, or is the shape of a module * with no call or construct signatures. @@ -16570,7 +16596,10 @@ namespace ts { return type; } if (assumeTrue) { - const narrowedType = filterType(type, t => areTypesComparable(t, valueType)); + const filterFn: (t: Type) => boolean = operator === SyntaxKind.EqualsEqualsToken ? + (t => areTypesComparable(t, valueType) || isCoercibleUnderDoubleEquals(t, valueType)) : + t => areTypesComparable(t, valueType); + const narrowedType = filterType(type, filterFn); return narrowedType.flags & TypeFlags.Never ? type : replacePrimitivesWithLiterals(narrowedType, valueType); } if (isUnitType(valueType)) { diff --git a/tests/baselines/reference/narrowByEquality.errors.txt b/tests/baselines/reference/narrowByEquality.errors.txt new file mode 100644 index 0000000000000..b391c4a07a1c4 --- /dev/null +++ b/tests/baselines/reference/narrowByEquality.errors.txt @@ -0,0 +1,71 @@ +tests/cases/compiler/narrowByEquality.ts(53,15): error TS2322: Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/compiler/narrowByEquality.ts(54,9): error TS2322: Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. + + +==== tests/cases/compiler/narrowByEquality.ts (2 errors) ==== + declare let x: number | string | boolean + declare let n: number; + declare let s: string; + declare let b: boolean; + + if (x == n) { + x; + } + + if (x == s) { + x; + } + + if (x == b) { + x; + } + + if (x == 1) { + x; + } + + if (x == "") { + x; + } + + if (x == "foo") { + x; + } + + if (x == true) { + x; + } + + if (x == false) { + x; + } + + declare let xAndObj: number | string | boolean | object + + if (xAndObj == {}) { + xAndObj; + } + + if (x == xAndObj) { + x; + xAndObj; + } + + // Repro from #24991 + + function test(level: number | string):number { + if (level == +level) { + const q2: number = level; // error + ~~ +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. + return level; + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. + } + return 0; + } + \ No newline at end of file diff --git a/tests/baselines/reference/narrowByEquality.js b/tests/baselines/reference/narrowByEquality.js new file mode 100644 index 0000000000000..a843040db7795 --- /dev/null +++ b/tests/baselines/reference/narrowByEquality.js @@ -0,0 +1,101 @@ +//// [narrowByEquality.ts] +declare let x: number | string | boolean +declare let n: number; +declare let s: string; +declare let b: boolean; + +if (x == n) { + x; +} + +if (x == s) { + x; +} + +if (x == b) { + x; +} + +if (x == 1) { + x; +} + +if (x == "") { + x; +} + +if (x == "foo") { + x; +} + +if (x == true) { + x; +} + +if (x == false) { + x; +} + +declare let xAndObj: number | string | boolean | object + +if (xAndObj == {}) { + xAndObj; +} + +if (x == xAndObj) { + x; + xAndObj; +} + +// Repro from #24991 + +function test(level: number | string):number { + if (level == +level) { + const q2: number = level; // error + return level; + } + return 0; +} + + +//// [narrowByEquality.js] +"use strict"; +if (x == n) { + x; +} +if (x == s) { + x; +} +if (x == b) { + x; +} +if (x == 1) { + x; +} +if (x == "") { + x; +} +if (x == "foo") { + x; +} +if (x == true) { + x; +} +if (x == false) { + x; +} +if (xAndObj == {}) { + xAndObj; +} +if (x == xAndObj) { + x; + xAndObj; +} +// Repro from #24991 +function test(level) { + if (level == +level) { + var q2 = level; // error + return level; + } + return 0; +} diff --git a/tests/baselines/reference/narrowByEquality.symbols b/tests/baselines/reference/narrowByEquality.symbols new file mode 100644 index 0000000000000..02e2ae138d98e --- /dev/null +++ b/tests/baselines/reference/narrowByEquality.symbols @@ -0,0 +1,113 @@ +=== tests/cases/compiler/narrowByEquality.ts === +declare let x: number | string | boolean +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) + +declare let n: number; +>n : Symbol(n, Decl(narrowByEquality.ts, 1, 11)) + +declare let s: string; +>s : Symbol(s, Decl(narrowByEquality.ts, 2, 11)) + +declare let b: boolean; +>b : Symbol(b, Decl(narrowByEquality.ts, 3, 11)) + +if (x == n) { +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +>n : Symbol(n, Decl(narrowByEquality.ts, 1, 11)) + + x; +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +} + +if (x == s) { +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +>s : Symbol(s, Decl(narrowByEquality.ts, 2, 11)) + + x; +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +} + +if (x == b) { +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +>b : Symbol(b, Decl(narrowByEquality.ts, 3, 11)) + + x; +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +} + +if (x == 1) { +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) + + x; +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +} + +if (x == "") { +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) + + x; +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +} + +if (x == "foo") { +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) + + x; +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +} + +if (x == true) { +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) + + x; +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +} + +if (x == false) { +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) + + x; +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +} + +declare let xAndObj: number | string | boolean | object +>xAndObj : Symbol(xAndObj, Decl(narrowByEquality.ts, 37, 11)) + +if (xAndObj == {}) { +>xAndObj : Symbol(xAndObj, Decl(narrowByEquality.ts, 37, 11)) + + xAndObj; +>xAndObj : Symbol(xAndObj, Decl(narrowByEquality.ts, 37, 11)) +} + +if (x == xAndObj) { +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) +>xAndObj : Symbol(xAndObj, Decl(narrowByEquality.ts, 37, 11)) + + x; +>x : Symbol(x, Decl(narrowByEquality.ts, 0, 11)) + + xAndObj; +>xAndObj : Symbol(xAndObj, Decl(narrowByEquality.ts, 37, 11)) +} + +// Repro from #24991 + +function test(level: number | string):number { +>test : Symbol(test, Decl(narrowByEquality.ts, 46, 1)) +>level : Symbol(level, Decl(narrowByEquality.ts, 50, 14)) + + if (level == +level) { +>level : Symbol(level, Decl(narrowByEquality.ts, 50, 14)) +>level : Symbol(level, Decl(narrowByEquality.ts, 50, 14)) + + const q2: number = level; // error +>q2 : Symbol(q2, Decl(narrowByEquality.ts, 52, 13)) +>level : Symbol(level, Decl(narrowByEquality.ts, 50, 14)) + + return level; +>level : Symbol(level, Decl(narrowByEquality.ts, 50, 14)) + } + return 0; +} + diff --git a/tests/baselines/reference/narrowByEquality.types b/tests/baselines/reference/narrowByEquality.types new file mode 100644 index 0000000000000..833e7537d68e8 --- /dev/null +++ b/tests/baselines/reference/narrowByEquality.types @@ -0,0 +1,132 @@ +=== tests/cases/compiler/narrowByEquality.ts === +declare let x: number | string | boolean +>x : string | number | boolean + +declare let n: number; +>n : number + +declare let s: string; +>s : string + +declare let b: boolean; +>b : boolean + +if (x == n) { +>x == n : boolean +>x : string | number | boolean +>n : number + + x; +>x : string | number | boolean +} + +if (x == s) { +>x == s : boolean +>x : string | number | boolean +>s : string + + x; +>x : string | number | boolean +} + +if (x == b) { +>x == b : boolean +>x : string | number | boolean +>b : boolean + + x; +>x : string | number | boolean +} + +if (x == 1) { +>x == 1 : boolean +>x : string | number | boolean +>1 : 1 + + x; +>x : 1 +} + +if (x == "") { +>x == "" : boolean +>x : string | number | boolean +>"" : "" + + x; +>x : "" +} + +if (x == "foo") { +>x == "foo" : boolean +>x : string | number | boolean +>"foo" : "foo" + + x; +>x : "foo" +} + +if (x == true) { +>x == true : boolean +>x : string | number | boolean +>true : true + + x; +>x : true +} + +if (x == false) { +>x == false : boolean +>x : string | number | boolean +>false : false + + x; +>x : false +} + +declare let xAndObj: number | string | boolean | object +>xAndObj : string | number | boolean | object + +if (xAndObj == {}) { +>xAndObj == {} : boolean +>xAndObj : string | number | boolean | object +>{} : {} + + xAndObj; +>xAndObj : object +} + +if (x == xAndObj) { +>x == xAndObj : boolean +>x : string | number | boolean +>xAndObj : string | number | boolean | object + + x; +>x : string | number | boolean + + xAndObj; +>xAndObj : string | number | boolean +} + +// Repro from #24991 + +function test(level: number | string):number { +>test : (level: string | number) => number +>level : string | number + + if (level == +level) { +>level == +level : boolean +>level : string | number +>+level : number +>level : string | number + + const q2: number = level; // error +>q2 : number +>level : string | number + + return level; +>level : string | number + } + return 0; +>0 : 0 +} + diff --git a/tests/cases/compiler/narrowByEquality.ts b/tests/cases/compiler/narrowByEquality.ts new file mode 100644 index 0000000000000..a0ebe09a9a9a7 --- /dev/null +++ b/tests/cases/compiler/narrowByEquality.ts @@ -0,0 +1,59 @@ +// @strict: true + +declare let x: number | string | boolean +declare let n: number; +declare let s: string; +declare let b: boolean; + +if (x == n) { + x; +} + +if (x == s) { + x; +} + +if (x == b) { + x; +} + +if (x == 1) { + x; +} + +if (x == "") { + x; +} + +if (x == "foo") { + x; +} + +if (x == true) { + x; +} + +if (x == false) { + x; +} + +declare let xAndObj: number | string | boolean | object + +if (xAndObj == {}) { + xAndObj; +} + +if (x == xAndObj) { + x; + xAndObj; +} + +// Repro from #24991 + +function test(level: number | string):number { + if (level == +level) { + const q2: number = level; // error + return level; + } + return 0; +} From d934401265403de077bdf4782c967c0832874003 Mon Sep 17 00:00:00 2001 From: Clay Miller Date: Fri, 26 Apr 2019 13:07:14 -0700 Subject: [PATCH 30/33] Change the type of 'uriComponent' (passed to 'encodeURIComponent') from 'string' to 'string | number | boolean'. Fixes #18159 (#31103) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - According to the ECMAScript 5.1 spec (§15.1.3.4), 'encodeURIComponent' invokes the abstract operation 'ToString': https://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3.4 - In the spec (§9.8), 'ToString' accepts an 'Undefined', 'Null', 'Boolean', 'Number', 'String' or 'Object' argument: https://www.ecma-international.org/ecma-262/5.1/#sec-9.8 - TypeScript’s 'StringConstructor' accepts an argument with type 'any': https://github.com/Microsoft/TypeScript/blob/b0100100a18d740ad0b7c626bc81b800b5273ece/lib/lib.es5.d.ts#L518 --- src/lib/es5.d.ts | 2 +- tests/baselines/reference/1.0lib-noErrors.js | 4 ++-- tests/baselines/reference/1.0lib-noErrors.symbols | 11 ++++++----- tests/baselines/reference/1.0lib-noErrors.types | 7 ++++--- .../reference/parserRegularExpression4.types | 2 +- tests/cases/conformance/decorators/1.0lib-noErrors.ts | 4 ++-- tests/lib/lib.d.ts | 2 +- 7 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 994fb1d765330..d39613e515194 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -60,7 +60,7 @@ declare function encodeURI(uri: string): string; * Encodes a text string as a valid component of a Uniform Resource Identifier (URI). * @param uriComponent A value representing an encoded URI component. */ -declare function encodeURIComponent(uriComponent: string): string; +declare function encodeURIComponent(uriComponent: string | number | boolean): string; /** * Computes a new string in which certain characters have been replaced by a hexadecimal escape sequence. diff --git a/tests/baselines/reference/1.0lib-noErrors.js b/tests/baselines/reference/1.0lib-noErrors.js index ade0f4bf903b9..3dac98d9e5647 100644 --- a/tests/baselines/reference/1.0lib-noErrors.js +++ b/tests/baselines/reference/1.0lib-noErrors.js @@ -78,7 +78,7 @@ declare function encodeURI(uri: string): string; * Encodes a text string as a valid component of a Uniform Resource Identifier (URI). * @param uriComponent A value representing an encoded URI component. */ -declare function encodeURIComponent(uriComponent: string): string; +declare function encodeURIComponent(uriComponent: string | number | boolean): string; interface PropertyDescriptor { configurable?: boolean; @@ -1141,7 +1141,7 @@ declare var Array: { (...items: T[]): T[]; isArray(arg: any): boolean; prototype: Array; -} +} //// [1.0lib-noErrors.js] /* ***************************************************************************** diff --git a/tests/baselines/reference/1.0lib-noErrors.symbols b/tests/baselines/reference/1.0lib-noErrors.symbols index adedbdb9aa2dc..d67952e201c98 100644 --- a/tests/baselines/reference/1.0lib-noErrors.symbols +++ b/tests/baselines/reference/1.0lib-noErrors.symbols @@ -98,12 +98,12 @@ declare function encodeURI(uri: string): string; * Encodes a text string as a valid component of a Uniform Resource Identifier (URI). * @param uriComponent A value representing an encoded URI component. */ -declare function encodeURIComponent(uriComponent: string): string; +declare function encodeURIComponent(uriComponent: string | number | boolean): string; >encodeURIComponent : Symbol(encodeURIComponent, Decl(1.0lib-noErrors.ts, 73, 48)) >uriComponent : Symbol(uriComponent, Decl(1.0lib-noErrors.ts, 79, 36)) interface PropertyDescriptor { ->PropertyDescriptor : Symbol(PropertyDescriptor, Decl(1.0lib-noErrors.ts, 79, 66)) +>PropertyDescriptor : Symbol(PropertyDescriptor, Decl(1.0lib-noErrors.ts, 79, 85)) configurable?: boolean; >configurable : Symbol(PropertyDescriptor.configurable, Decl(1.0lib-noErrors.ts, 81, 30)) @@ -130,7 +130,7 @@ interface PropertyDescriptorMap { [s: string]: PropertyDescriptor; >s : Symbol(s, Decl(1.0lib-noErrors.ts, 91, 5)) ->PropertyDescriptor : Symbol(PropertyDescriptor, Decl(1.0lib-noErrors.ts, 79, 66)) +>PropertyDescriptor : Symbol(PropertyDescriptor, Decl(1.0lib-noErrors.ts, 79, 85)) } interface Object { @@ -217,7 +217,7 @@ declare var Object: { >getOwnPropertyDescriptor : Symbol(getOwnPropertyDescriptor, Decl(1.0lib-noErrors.ts, 141, 32)) >o : Symbol(o, Decl(1.0lib-noErrors.ts, 149, 29)) >p : Symbol(p, Decl(1.0lib-noErrors.ts, 149, 36)) ->PropertyDescriptor : Symbol(PropertyDescriptor, Decl(1.0lib-noErrors.ts, 79, 66)) +>PropertyDescriptor : Symbol(PropertyDescriptor, Decl(1.0lib-noErrors.ts, 79, 85)) /** * Returns the names of the own properties of an object. The own properties of an object are those that are defined directly @@ -250,7 +250,7 @@ declare var Object: { >o : Symbol(o, Decl(1.0lib-noErrors.ts, 171, 19)) >p : Symbol(p, Decl(1.0lib-noErrors.ts, 171, 26)) >attributes : Symbol(attributes, Decl(1.0lib-noErrors.ts, 171, 37)) ->PropertyDescriptor : Symbol(PropertyDescriptor, Decl(1.0lib-noErrors.ts, 79, 66)) +>PropertyDescriptor : Symbol(PropertyDescriptor, Decl(1.0lib-noErrors.ts, 79, 85)) /** * Adds one or more properties to an object, and/or modifies attributes of existing properties. @@ -2084,3 +2084,4 @@ declare var Array: { >prototype : Symbol(prototype, Decl(1.0lib-noErrors.ts, 1140, 31)) >Array : Symbol(Array, Decl(1.0lib-noErrors.ts, 973, 23), Decl(1.0lib-noErrors.ts, 1133, 11)) } + diff --git a/tests/baselines/reference/1.0lib-noErrors.types b/tests/baselines/reference/1.0lib-noErrors.types index 1d9c67834e702..91e5fdc7b7356 100644 --- a/tests/baselines/reference/1.0lib-noErrors.types +++ b/tests/baselines/reference/1.0lib-noErrors.types @@ -98,9 +98,9 @@ declare function encodeURI(uri: string): string; * Encodes a text string as a valid component of a Uniform Resource Identifier (URI). * @param uriComponent A value representing an encoded URI component. */ -declare function encodeURIComponent(uriComponent: string): string; ->encodeURIComponent : (uriComponent: string) => string ->uriComponent : string +declare function encodeURIComponent(uriComponent: string | number | boolean): string; +>encodeURIComponent : (uriComponent: string | number | boolean) => string +>uriComponent : string | number | boolean interface PropertyDescriptor { configurable?: boolean; @@ -1911,3 +1911,4 @@ declare var Array: { prototype: Array; >prototype : any[] } + diff --git a/tests/baselines/reference/parserRegularExpression4.types b/tests/baselines/reference/parserRegularExpression4.types index 1a0db05a48e48..1af56c7a24fc6 100644 --- a/tests/baselines/reference/parserRegularExpression4.types +++ b/tests/baselines/reference/parserRegularExpression4.types @@ -61,7 +61,7 @@ if (Ca.test(c.href) || Ba.test(c.href) && /(\\?|&)adurl=/.test(c.href) && !/(\\? >"&q=" + encodeURIComponent(W("q") || W("as_q") || A) : string >"&q=" : "&q=" >encodeURIComponent(W("q") || W("as_q") || A) : string ->encodeURIComponent : (uriComponent: string) => string +>encodeURIComponent : (uriComponent: string | number | boolean) => string >W("q") || W("as_q") || A : any >W("q") || W("as_q") : any >W("q") : any diff --git a/tests/cases/conformance/decorators/1.0lib-noErrors.ts b/tests/cases/conformance/decorators/1.0lib-noErrors.ts index 6966e3e70d07d..391c0926a82b7 100644 --- a/tests/cases/conformance/decorators/1.0lib-noErrors.ts +++ b/tests/cases/conformance/decorators/1.0lib-noErrors.ts @@ -78,7 +78,7 @@ declare function encodeURI(uri: string): string; * Encodes a text string as a valid component of a Uniform Resource Identifier (URI). * @param uriComponent A value representing an encoded URI component. */ -declare function encodeURIComponent(uriComponent: string): string; +declare function encodeURIComponent(uriComponent: string | number | boolean): string; interface PropertyDescriptor { configurable?: boolean; @@ -1141,4 +1141,4 @@ declare var Array: { (...items: T[]): T[]; isArray(arg: any): boolean; prototype: Array; -} \ No newline at end of file +} \ No newline at end of file diff --git a/tests/lib/lib.d.ts b/tests/lib/lib.d.ts index ad17bec673e95..5f089bb3c82eb 100644 --- a/tests/lib/lib.d.ts +++ b/tests/lib/lib.d.ts @@ -77,7 +77,7 @@ declare function encodeURI(uri: string): string; * Encodes a text string as a valid component of a Uniform Resource Identifier (URI). * @param uriComponent A value representing an encoded URI component. */ -declare function encodeURIComponent(uriComponent: string): string; +declare function encodeURIComponent(uriComponent: string | number | boolean): string; /** * Computes a new string in which certain characters have been replaced by a hexadecimal escape sequence. From 454b4280b11d87c1e043f26d190af0e0f214439c Mon Sep 17 00:00:00 2001 From: Wenlu Wang Date: Fri, 26 Apr 2019 16:00:04 -0500 Subject: [PATCH 31/33] check more case for empty binding patten (#25263) * check more case for empty binding patten * refactor binding pattern checking getWidenedType * fix spelling * fix merge and rebase --- src/compiler/checker.ts | 28 +++++++++--- ...destructuringAssignabilityCheck.errors.txt | 43 +++++++++++++++++++ .../destructuringAssignabilityCheck.js | 32 ++++++++++++++ .../destructuringAssignabilityCheck.symbols | 24 +++++++++++ .../destructuringAssignabilityCheck.types | 40 +++++++++++++++++ .../strictNullEmptyDestructuring.errors.txt | 5 ++- .../destructuringAssignabilityCheck.ts | 17 ++++++++ 7 files changed, 181 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/destructuringAssignabilityCheck.errors.txt create mode 100644 tests/baselines/reference/destructuringAssignabilityCheck.js create mode 100644 tests/baselines/reference/destructuringAssignabilityCheck.symbols create mode 100644 tests/baselines/reference/destructuringAssignabilityCheck.types create mode 100644 tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 913d7f3b2a91a..8ee0a4c051996 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26462,14 +26462,28 @@ namespace ts { } // For a binding pattern, validate the initializer and exit if (isBindingPattern(node.name)) { - // Don't validate for-in initializer as it is already an error - if (node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement) { - const initializerType = checkExpressionCached(node.initializer); - if (strictNullChecks && node.name.elements.length === 0) { - checkNonNullNonVoidType(initializerType, node); + const needCheckInitializer = node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement; + const needCheckWidenedType = node.name.elements.length === 0; + if (needCheckInitializer || needCheckWidenedType) { + // Don't validate for-in initializer as it is already an error + const widenedType = getWidenedTypeForVariableLikeDeclaration(node); + if (needCheckInitializer) { + const initializerType = checkExpressionCached(node.initializer!); + if (strictNullChecks && needCheckWidenedType) { + checkNonNullNonVoidType(initializerType, node); + } + else { + checkTypeAssignableToAndOptionallyElaborate(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, node.initializer); + } } - else { - checkTypeAssignableToAndOptionallyElaborate(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, node.initializer); + // check the binding pattern with empty elements + if (needCheckWidenedType) { + if (isArrayBindingPattern(node.name)) { + checkIteratedTypeOrElementType(widenedType, node, /* allowStringInput */ false, /* allowAsyncIterables */ false); + } + else if (strictNullChecks) { + checkNonNullNonVoidType(widenedType, node); + } } } return; diff --git a/tests/baselines/reference/destructuringAssignabilityCheck.errors.txt b/tests/baselines/reference/destructuringAssignabilityCheck.errors.txt new file mode 100644 index 0000000000000..bbb4812cf00ed --- /dev/null +++ b/tests/baselines/reference/destructuringAssignabilityCheck.errors.txt @@ -0,0 +1,43 @@ +tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(1,7): error TS2461: Type '{}' is not an array type. +tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(2,7): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(3,3): error TS2461: Type '{}' is not an array type. +tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(4,3): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(6,14): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(9,14): error TS2461: Type '{}' is not an array type. +tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(13,7): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts(15,7): error TS2461: Type '{}' is not an array type. + + +==== tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts (8 errors) ==== + const [] = {}; // should be error + ~~ +!!! error TS2461: Type '{}' is not an array type. + const {} = undefined; // error correctly + ~~ +!!! error TS2532: Object is possibly 'undefined'. + (([]) => 0)({}); // should be error + ~~ +!!! error TS2461: Type '{}' is not an array type. + (({}) => 0)(undefined); // should be error + ~~ +!!! error TS2532: Object is possibly 'undefined'. + + function foo({}: undefined) { + ~~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + return 0 + } + function bar([]: {}) { + ~~~~~~ +!!! error TS2461: Type '{}' is not an array type. + return 0 + } + + const { }: undefined = 1 + ~~~ +!!! error TS2532: Object is possibly 'undefined'. + + const []: {} = {} + ~~ +!!! error TS2461: Type '{}' is not an array type. + \ No newline at end of file diff --git a/tests/baselines/reference/destructuringAssignabilityCheck.js b/tests/baselines/reference/destructuringAssignabilityCheck.js new file mode 100644 index 0000000000000..2702d8b7f5c59 --- /dev/null +++ b/tests/baselines/reference/destructuringAssignabilityCheck.js @@ -0,0 +1,32 @@ +//// [destructuringAssignabilityCheck.ts] +const [] = {}; // should be error +const {} = undefined; // error correctly +(([]) => 0)({}); // should be error +(({}) => 0)(undefined); // should be error + +function foo({}: undefined) { + return 0 +} +function bar([]: {}) { + return 0 +} + +const { }: undefined = 1 + +const []: {} = {} + + +//// [destructuringAssignabilityCheck.js] +"use strict"; +var _a = {}; // should be error +var _b = undefined; // error correctly +(function (_a) { return 0; })({}); // should be error +(function (_a) { return 0; })(undefined); // should be error +function foo(_a) { + return 0; +} +function bar(_a) { + return 0; +} +var _c = 1; +var _d = {}; diff --git a/tests/baselines/reference/destructuringAssignabilityCheck.symbols b/tests/baselines/reference/destructuringAssignabilityCheck.symbols new file mode 100644 index 0000000000000..c9465f0e41aea --- /dev/null +++ b/tests/baselines/reference/destructuringAssignabilityCheck.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts === +const [] = {}; // should be error +const {} = undefined; // error correctly +>undefined : Symbol(undefined) + +(([]) => 0)({}); // should be error +(({}) => 0)(undefined); // should be error +>undefined : Symbol(undefined) + +function foo({}: undefined) { +>foo : Symbol(foo, Decl(destructuringAssignabilityCheck.ts, 3, 23)) + + return 0 +} +function bar([]: {}) { +>bar : Symbol(bar, Decl(destructuringAssignabilityCheck.ts, 7, 1)) + + return 0 +} + +const { }: undefined = 1 + +const []: {} = {} + diff --git a/tests/baselines/reference/destructuringAssignabilityCheck.types b/tests/baselines/reference/destructuringAssignabilityCheck.types new file mode 100644 index 0000000000000..df4467cce6433 --- /dev/null +++ b/tests/baselines/reference/destructuringAssignabilityCheck.types @@ -0,0 +1,40 @@ +=== tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts === +const [] = {}; // should be error +>{} : {} + +const {} = undefined; // error correctly +>undefined : undefined + +(([]) => 0)({}); // should be error +>(([]) => 0)({}) : number +>(([]) => 0) : ([]: {}) => number +>([]) => 0 : ([]: {}) => number +>0 : 0 +>{} : {} + +(({}) => 0)(undefined); // should be error +>(({}) => 0)(undefined) : number +>(({}) => 0) : ({}: undefined) => number +>({}) => 0 : ({}: undefined) => number +>0 : 0 +>undefined : undefined + +function foo({}: undefined) { +>foo : ({}: undefined) => number + + return 0 +>0 : 0 +} +function bar([]: {}) { +>bar : ([]: {}) => number + + return 0 +>0 : 0 +} + +const { }: undefined = 1 +>1 : 1 + +const []: {} = {} +>{} : {} + diff --git a/tests/baselines/reference/strictNullEmptyDestructuring.errors.txt b/tests/baselines/reference/strictNullEmptyDestructuring.errors.txt index 2406ac27d98a1..cb50303d3500d 100644 --- a/tests/baselines/reference/strictNullEmptyDestructuring.errors.txt +++ b/tests/baselines/reference/strictNullEmptyDestructuring.errors.txt @@ -1,3 +1,4 @@ +tests/cases/compiler/strictNullEmptyDestructuring.ts(3,5): error TS2461: Type 'null' is not an array type. tests/cases/compiler/strictNullEmptyDestructuring.ts(3,5): error TS2531: Object is possibly 'null'. tests/cases/compiler/strictNullEmptyDestructuring.ts(5,5): error TS2531: Object is possibly 'null'. tests/cases/compiler/strictNullEmptyDestructuring.ts(7,2): error TS2531: Object is possibly 'null'. @@ -11,11 +12,13 @@ tests/cases/compiler/strictNullEmptyDestructuring.ts(21,5): error TS2533: Object tests/cases/compiler/strictNullEmptyDestructuring.ts(23,2): error TS2533: Object is possibly 'null' or 'undefined'. -==== tests/cases/compiler/strictNullEmptyDestructuring.ts (11 errors) ==== +==== tests/cases/compiler/strictNullEmptyDestructuring.ts (12 errors) ==== // Repro from #20873 let [] = null; ~~ +!!! error TS2461: Type 'null' is not an array type. + ~~ !!! error TS2531: Object is possibly 'null'. let { } = null; diff --git a/tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts b/tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts new file mode 100644 index 0000000000000..af595c1621f96 --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/destructuringAssignabilityCheck.ts @@ -0,0 +1,17 @@ +// @strict: true + +const [] = {}; // should be error +const {} = undefined; // error correctly +(([]) => 0)({}); // should be error +(({}) => 0)(undefined); // should be error + +function foo({}: undefined) { + return 0 +} +function bar([]: {}) { + return 0 +} + +const { }: undefined = 1 + +const []: {} = {} From 57a8ee1507d2e14f3d7efd8bd53ff049e573afbf Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Sat, 27 Apr 2019 16:47:27 -0700 Subject: [PATCH 32/33] Fix binder performance regression --- src/compiler/checker.ts | 18 +++++++++++++++--- .../reference/globalThisCollision.errors.txt | 7 +++++++ .../reference/globalThisCollision.symbols | 4 ++++ .../reference/globalThisCollision.types | 4 ++++ .../conformance/es2019/globalThisCollision.ts | 5 +++++ 5 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/globalThisCollision.errors.txt create mode 100644 tests/baselines/reference/globalThisCollision.symbols create mode 100644 tests/baselines/reference/globalThisCollision.types create mode 100644 tests/cases/conformance/es2019/globalThisCollision.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8ee0a4c051996..33d2dd73876b8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -94,8 +94,6 @@ namespace ts { const globalThisSymbol = createSymbol(SymbolFlags.Module, "globalThis" as __String, CheckFlags.Readonly); globalThisSymbol.exports = globals; - globalThisSymbol.valueDeclaration = createNode(SyntaxKind.Identifier) as Identifier; - (globalThisSymbol.valueDeclaration as Identifier).escapedText = "globalThis" as __String; globals.set(globalThisSymbol.escapedName, globalThisSymbol); const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as __String); @@ -926,7 +924,12 @@ namespace ts { recordMergedSymbol(target, source); } else if (target.flags & SymbolFlags.NamespaceModule) { - error(getNameOfDeclaration(source.declarations[0]), Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); + // Do not report an error when merging `var globalThis` with the built-in `globalThis`, + // as we will already report a "Declaration name conflicts..." error, and this error + // won't make much sense. + if (target !== globalThisSymbol) { + error(getNameOfDeclaration(source.declarations[0]), Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); + } } else { // error const isEitherEnum = !!(target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum); @@ -30456,6 +30459,14 @@ namespace ts { continue; } if (!isExternalOrCommonJsModule(file)) { + // It is an error for a non-external-module (i.e. script) to declare its own `globalThis`. + // We can't use `builtinGlobals` for this due to synthetic expando-namespace generation in JS files. + const fileGlobalThisSymbol = file.locals!.get("globalThis" as __String); + if (fileGlobalThisSymbol) { + for (const declaration of fileGlobalThisSymbol.declarations) { + diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, "globalThis")); + } + } mergeSymbolTable(globals, file.locals!); } if (file.jsGlobalAugmentations) { @@ -30501,6 +30512,7 @@ namespace ts { getSymbolLinks(undefinedSymbol).type = undefinedWideningType; getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as __String, /*arity*/ 0, /*reportErrors*/ true); getSymbolLinks(unknownSymbol).type = errorType; + getSymbolLinks(globalThisSymbol).type = createObjectType(ObjectFlags.Anonymous, globalThisSymbol); // Initialize special types globalArrayType = getGlobalType("Array" as __String, /*arity*/ 1, /*reportErrors*/ true); diff --git a/tests/baselines/reference/globalThisCollision.errors.txt b/tests/baselines/reference/globalThisCollision.errors.txt new file mode 100644 index 0000000000000..ea0fb9d9f434b --- /dev/null +++ b/tests/baselines/reference/globalThisCollision.errors.txt @@ -0,0 +1,7 @@ +tests/cases/conformance/es2019/globalThisCollision.js(1,5): error TS2397: Declaration name conflicts with built-in global identifier 'globalThis'. + + +==== tests/cases/conformance/es2019/globalThisCollision.js (1 errors) ==== + var globalThis; + ~~~~~~~~~~ +!!! error TS2397: Declaration name conflicts with built-in global identifier 'globalThis'. \ No newline at end of file diff --git a/tests/baselines/reference/globalThisCollision.symbols b/tests/baselines/reference/globalThisCollision.symbols new file mode 100644 index 0000000000000..088357fd537db --- /dev/null +++ b/tests/baselines/reference/globalThisCollision.symbols @@ -0,0 +1,4 @@ +=== tests/cases/conformance/es2019/globalThisCollision.js === +var globalThis; +>globalThis : Symbol(globalThis, Decl(globalThisCollision.js, 0, 3)) + diff --git a/tests/baselines/reference/globalThisCollision.types b/tests/baselines/reference/globalThisCollision.types new file mode 100644 index 0000000000000..476533be18cae --- /dev/null +++ b/tests/baselines/reference/globalThisCollision.types @@ -0,0 +1,4 @@ +=== tests/cases/conformance/es2019/globalThisCollision.js === +var globalThis; +>globalThis : any + diff --git a/tests/cases/conformance/es2019/globalThisCollision.ts b/tests/cases/conformance/es2019/globalThisCollision.ts new file mode 100644 index 0000000000000..d73a7b6217e64 --- /dev/null +++ b/tests/cases/conformance/es2019/globalThisCollision.ts @@ -0,0 +1,5 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @filename: globalThisCollision.js +var globalThis; \ No newline at end of file From 47d908161f1c25c50ed0ef42c67a13e1050d701c Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Mon, 29 Apr 2019 11:03:35 -0700 Subject: [PATCH 33/33] Update user baselines (#31161) --- tests/baselines/reference/user/assert.log | 2 +- .../user/chrome-devtools-frontend.log | 18 +--- tests/baselines/reference/user/prettier.log | 2 +- tests/baselines/reference/user/uglify-js.log | 98 +++++++++---------- 4 files changed, 55 insertions(+), 65 deletions(-) diff --git a/tests/baselines/reference/user/assert.log b/tests/baselines/reference/user/assert.log index 672c147428dee..60e693ae6f3ca 100644 --- a/tests/baselines/reference/user/assert.log +++ b/tests/baselines/reference/user/assert.log @@ -9,7 +9,7 @@ node_modules/assert/assert.js(130,10): error TS2339: Property 'generatedMessage' node_modules/assert/assert.js(132,10): error TS2339: Property 'message' does not exist on type 'typeof ok'. node_modules/assert/assert.js(133,10): error TS2339: Property 'generatedMessage' does not exist on type 'typeof ok'. node_modules/assert/assert.js(154,12): error TS2339: Property 'stack' does not exist on type 'typeof ok'. -node_modules/assert/test.js(25,5): error TS2367: This condition will always return 'false' since the types 'string | undefined' and 'boolean' have no overlap. +node_modules/assert/test.js(25,5): error TS2367: This condition will always return 'false' since the types 'string | undefined' and 'true' have no overlap. node_modules/assert/test.js(39,5): error TS2552: Cannot find name 'test'. Did you mean 'tests'? node_modules/assert/test.js(55,5): error TS2552: Cannot find name 'test'. Did you mean 'tests'? node_modules/assert/test.js(74,5): error TS2552: Cannot find name 'test'. Did you mean 'tests'? diff --git a/tests/baselines/reference/user/chrome-devtools-frontend.log b/tests/baselines/reference/user/chrome-devtools-frontend.log index 45afc61657ed1..45ba3fc971a56 100644 --- a/tests/baselines/reference/user/chrome-devtools-frontend.log +++ b/tests/baselines/reference/user/chrome-devtools-frontend.log @@ -869,16 +869,6 @@ node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighth node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(24079,1): error TS2323: Cannot redeclare exported variable 'Buf16'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(24080,1): error TS2323: Cannot redeclare exported variable 'Buf32'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(26059,1): error TS2323: Cannot redeclare exported variable 'deflate'. -node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(27915,27): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'. - Type 'number' is not assignable to type 'string'. -node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(27918,30): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'. - Type 'number' is not assignable to type 'string'. -node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(27921,30): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'. - Type 'number' is not assignable to type 'string'. -node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(27928,27): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'. - Type 'number' is not assignable to type 'string'. -node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(27929,20): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'. - Type 'number' is not assignable to type 'string'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(27956,16): error TS2323: Cannot redeclare exported variable 'parse'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(28222,51): error TS2300: Duplicate identifier '_read'. node_modules/chrome-devtools-frontend/front_end/audits2_worker/lighthouse/lighthouse-background.js(28457,20): error TS2339: Property 'emit' does not exist on type 'Readable'. @@ -5027,9 +5017,9 @@ node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(42,20): node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(42,125): error TS2339: Property 'length1' does not exist on type 'number'. node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(42,138): error TS2339: Property 'length2' does not exist on type 'number'. node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(43,411): error TS2403: Subsequent variable declarations must have the same type. Variable 'g' must be of type 'string', but here has type 'any'. -node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(43,443): error TS2367: This condition will always return 'false' since the types 'number' and 'string' have no overlap. -node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(44,7): error TS2367: This condition will always return 'false' since the types 'number' and 'string' have no overlap. -node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(44,220): error TS2367: This condition will always return 'false' since the types 'number' and 'string' have no overlap. +node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(43,443): error TS2367: This condition will always return 'false' since the types '1' and 'string' have no overlap. +node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(44,7): error TS2367: This condition will always return 'false' since the types '-1' and 'string' have no overlap. +node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(44,220): error TS2367: This condition will always return 'false' since the types '0' and 'string' have no overlap. node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(47,403): error TS2339: Property 'diffs' does not exist on type 'typeof diff_match_patch'. node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(47,417): error TS2339: Property 'start2' does not exist on type 'typeof diff_match_patch'. node_modules/chrome-devtools-frontend/front_end/diff/diff_match_patch.js(47,429): error TS2339: Property 'start1' does not exist on type 'typeof diff_match_patch'. @@ -10912,7 +10902,7 @@ node_modules/chrome-devtools-frontend/front_end/source_frame/SourcesTextEditor.j node_modules/chrome-devtools-frontend/front_end/source_frame/SourcesTextEditor.js(822,79): error TS2339: Property 'charAt' does not exist on type 'void'. node_modules/chrome-devtools-frontend/front_end/source_frame/SourcesTextEditor.js(823,41): error TS2339: Property 'length' does not exist on type 'void'. node_modules/chrome-devtools-frontend/front_end/source_frame/SourcesTextEditor.js(823,88): error TS2339: Property 'charAt' does not exist on type 'void'. -node_modules/chrome-devtools-frontend/front_end/source_frame/SourcesTextEditor.js(839,9): error TS2367: This condition will always return 'false' since the types 'void' and 'number' have no overlap. +node_modules/chrome-devtools-frontend/front_end/source_frame/SourcesTextEditor.js(839,9): error TS2367: This condition will always return 'false' since the types 'void' and '0' have no overlap. node_modules/chrome-devtools-frontend/front_end/source_frame/SourcesTextEditor.js(854,9): error TS1345: An expression of type 'void' cannot be tested for truthiness node_modules/chrome-devtools-frontend/front_end/source_frame/SourcesTextEditor.js(862,12): error TS1345: An expression of type 'void' cannot be tested for truthiness node_modules/chrome-devtools-frontend/front_end/source_frame/SourcesTextEditor.js(862,13): error TS1345: An expression of type 'void' cannot be tested for truthiness diff --git a/tests/baselines/reference/user/prettier.log b/tests/baselines/reference/user/prettier.log index 22c00d2bd46bb..6ee6e91cb6bc2 100644 --- a/tests/baselines/reference/user/prettier.log +++ b/tests/baselines/reference/user/prettier.log @@ -1,6 +1,6 @@ Exit Code: 1 Standard output: -node_modules/@typescript-eslint/typescript-estree/dist/parser.d.ts(1,8): error TS1192: Module '"/prettier/prettier/node_modules/typescript/lib/typescript"' has no default export. +node_modules/@typescript-eslint/typescript-estree/dist/parser.d.ts(1,8): error TS1259: Module '"/prettier/prettier/node_modules/typescript/lib/typescript"' can only be default-imported using the 'esModuleInterop' flag src/cli/util.js(60,44): error TS2345: Argument of type 'null' is not assignable to parameter of type 'number | undefined'. src/cli/util.js(119,38): error TS2339: Property 'sync' does not exist on type '(...args: any[]) => any'. src/cli/util.js(372,29): error TS2532: Object is possibly 'undefined'. diff --git a/tests/baselines/reference/user/uglify-js.log b/tests/baselines/reference/user/uglify-js.log index 8f4b868d5527a..c5feff00abc0d 100644 --- a/tests/baselines/reference/user/uglify-js.log +++ b/tests/baselines/reference/user/uglify-js.log @@ -10,58 +10,58 @@ node_modules/uglify-js/lib/ast.js(932,25): error TS2339: Property 'self' does no node_modules/uglify-js/lib/ast.js(933,37): error TS2339: Property 'parent' does not exist on type 'TreeWalker'. node_modules/uglify-js/lib/compress.js(175,42): error TS2554: Expected 0 arguments, but got 1. node_modules/uglify-js/lib/compress.js(532,41): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(855,33): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(1110,38): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(1124,51): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'true | ((node: any) => any)' has no compatible call signatures. -node_modules/uglify-js/lib/compress.js(1188,53): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(1229,112): error TS2454: Variable 'args' is used before being assigned. -node_modules/uglify-js/lib/compress.js(1230,29): error TS2532: Object is possibly 'undefined'. -node_modules/uglify-js/lib/compress.js(1239,87): error TS2322: Type 'false' is not assignable to type 'number'. -node_modules/uglify-js/lib/compress.js(1247,29): error TS2322: Type 'false' is not assignable to type 'never'. -node_modules/uglify-js/lib/compress.js(1353,53): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(1454,38): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(1564,42): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(1596,41): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(1708,49): error TS2345: Argument of type 'number[]' is not assignable to parameter of type '[number, number, ...never[]]'. +node_modules/uglify-js/lib/compress.js(858,33): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(1114,38): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(1128,51): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'true | ((node: any) => any)' has no compatible call signatures. +node_modules/uglify-js/lib/compress.js(1192,53): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(1233,112): error TS2454: Variable 'args' is used before being assigned. +node_modules/uglify-js/lib/compress.js(1234,29): error TS2532: Object is possibly 'undefined'. +node_modules/uglify-js/lib/compress.js(1243,87): error TS2322: Type 'false' is not assignable to type 'number'. +node_modules/uglify-js/lib/compress.js(1251,29): error TS2322: Type 'false' is not assignable to type 'never'. +node_modules/uglify-js/lib/compress.js(1359,53): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(1460,38): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(1570,42): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(1602,41): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(1714,49): error TS2345: Argument of type 'number[]' is not assignable to parameter of type '[number, number, ...never[]]'. Type 'number[]' is missing the following properties from type '[number, number, ...never[]]': 0, 1 -node_modules/uglify-js/lib/compress.js(2031,59): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(2069,53): error TS2345: Argument of type 'any[]' is not assignable to parameter of type '[number, number, ...never[]]'. +node_modules/uglify-js/lib/compress.js(2037,59): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(2075,53): error TS2345: Argument of type 'any[]' is not assignable to parameter of type '[number, number, ...never[]]'. Type 'any[]' is missing the following properties from type '[number, number, ...never[]]': 0, 1 -node_modules/uglify-js/lib/compress.js(2217,34): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(2883,42): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3328,38): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3341,33): error TS2322: Type '"f"' is not assignable to type 'boolean'. -node_modules/uglify-js/lib/compress.js(3475,33): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3528,29): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3545,29): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(3570,75): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3643,63): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3828,38): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(3849,24): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(3859,28): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. -node_modules/uglify-js/lib/compress.js(4018,21): error TS2403: Subsequent variable declarations must have the same type. Variable 'defs' must be of type 'Dictionary & { set: (key: any, val: any) => Dictionary & { set: ...; add: (key: any, val: any) => Dictionary & { set: ...; add: ...; get: (key: any) => any; del: (key: any) => Dictionary & { set: ...; ... 8 more ...; toObject: () => any; }; ... 5 more ...; toObject: () => any; }; ... 7 more ...; toObject: () => any;...', but here has type 'any'. -node_modules/uglify-js/lib/compress.js(4070,17): error TS2447: The '|=' operator is not allowed for boolean types. Consider using '||' instead. -node_modules/uglify-js/lib/compress.js(4126,45): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(4238,33): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(4537,17): error TS2403: Subsequent variable declarations must have the same type. Variable 'body' must be of type 'any[]', but here has type 'any'. -node_modules/uglify-js/lib/compress.js(4621,37): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(4829,57): error TS2345: Argument of type 'any[]' is not assignable to parameter of type '[RegExp, (string | undefined)?]'. +node_modules/uglify-js/lib/compress.js(2223,34): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(2948,42): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3400,38): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3413,33): error TS2322: Type '"f"' is not assignable to type 'boolean'. +node_modules/uglify-js/lib/compress.js(3547,33): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3600,29): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3617,29): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(3642,75): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3715,63): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3900,38): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(3921,24): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(3931,28): error TS2339: Property 'parent' does not exist on type 'TreeTransformer'. +node_modules/uglify-js/lib/compress.js(4090,21): error TS2403: Subsequent variable declarations must have the same type. Variable 'defs' must be of type 'Dictionary & { set: (key: any, val: any) => Dictionary & { set: ...; add: (key: any, val: any) => Dictionary & { set: ...; add: ...; get: (key: any) => any; del: (key: any) => Dictionary & { set: ...; ... 8 more ...; toObject: () => any; }; ... 5 more ...; toObject: () => any; }; ... 7 more ...; toObject: () => any;...', but here has type 'any'. +node_modules/uglify-js/lib/compress.js(4142,17): error TS2447: The '|=' operator is not allowed for boolean types. Consider using '||' instead. +node_modules/uglify-js/lib/compress.js(4203,45): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(4315,33): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(4614,17): error TS2403: Subsequent variable declarations must have the same type. Variable 'body' must be of type 'any[]', but here has type 'any'. +node_modules/uglify-js/lib/compress.js(4698,37): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(4906,57): error TS2345: Argument of type 'any[]' is not assignable to parameter of type '[RegExp, (string | undefined)?]'. Property '0' is missing in type 'any[]' but required in type '[RegExp, (string | undefined)?]'. -node_modules/uglify-js/lib/compress.js(4987,45): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(4994,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'code' must be of type 'string', but here has type '{ get: () => string; toString: () => string; indent: () => void; indentation: () => number; current_width: () => number; should_break: () => boolean; has_parens: () => boolean; newline: () => void; print: (str: any) => void; ... 24 more ...; parent: (n: any) => any; }'. -node_modules/uglify-js/lib/compress.js(4998,36): error TS2532: Object is possibly 'undefined'. -node_modules/uglify-js/lib/compress.js(5003,41): error TS2339: Property 'get' does not exist on type 'string'. -node_modules/uglify-js/lib/compress.js(5490,18): error TS2454: Variable 'is_strict_comparison' is used before being assigned. -node_modules/uglify-js/lib/compress.js(5922,25): error TS2367: This condition will always return 'false' since the types 'boolean' and '"f"' have no overlap. -node_modules/uglify-js/lib/compress.js(5949,47): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(6023,39): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(6095,39): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(6101,41): error TS2554: Expected 0 arguments, but got 1. -node_modules/uglify-js/lib/compress.js(6534,43): error TS2454: Variable 'property' is used before being assigned. -node_modules/uglify-js/lib/compress.js(6549,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'value' must be of type 'number', but here has type 'any'. -node_modules/uglify-js/lib/compress.js(6552,46): error TS2339: Property 'has_side_effects' does not exist on type 'number'. -node_modules/uglify-js/lib/compress.js(6558,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'value' must be of type 'number', but here has type 'any'. -node_modules/uglify-js/lib/compress.js(6586,34): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(5070,45): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(5077,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'code' must be of type 'string', but here has type '{ get: () => string; toString: () => string; indent: () => void; indentation: () => number; current_width: () => number; should_break: () => boolean; has_parens: () => boolean; newline: () => void; print: (str: any) => void; ... 24 more ...; parent: (n: any) => any; }'. +node_modules/uglify-js/lib/compress.js(5081,36): error TS2532: Object is possibly 'undefined'. +node_modules/uglify-js/lib/compress.js(5086,41): error TS2339: Property 'get' does not exist on type 'string'. +node_modules/uglify-js/lib/compress.js(5589,18): error TS2454: Variable 'is_strict_comparison' is used before being assigned. +node_modules/uglify-js/lib/compress.js(6084,25): error TS2367: This condition will always return 'false' since the types 'boolean' and '"f"' have no overlap. +node_modules/uglify-js/lib/compress.js(6111,47): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(6185,39): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(6257,39): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(6263,41): error TS2554: Expected 0 arguments, but got 1. +node_modules/uglify-js/lib/compress.js(6696,43): error TS2454: Variable 'property' is used before being assigned. +node_modules/uglify-js/lib/compress.js(6711,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'value' must be of type 'number', but here has type 'any'. +node_modules/uglify-js/lib/compress.js(6714,46): error TS2339: Property 'has_side_effects' does not exist on type 'number'. +node_modules/uglify-js/lib/compress.js(6720,25): error TS2403: Subsequent variable declarations must have the same type. Variable 'value' must be of type 'number', but here has type 'any'. +node_modules/uglify-js/lib/compress.js(6748,34): error TS2554: Expected 0 arguments, but got 1. node_modules/uglify-js/lib/minify.js(170,75): error TS2339: Property 'compress' does not exist on type 'Compressor'. node_modules/uglify-js/lib/mozilla-ast.js(566,33): error TS2554: Expected 0 arguments, but got 1. node_modules/uglify-js/lib/output.js(246,25): error TS2554: Expected 0 arguments, but got 2.