Allow e: unknown in catch arguments

In addition, allow an explicit `any`; anything else throws an error.

Also adjust and reorganize existing tests.

Fixes #36775.
This commit is contained in:
Eli Barzilay 2020-06-06 00:18:20 -04:00
parent 08cb0b23e8
commit ffa35d3272
19 changed files with 544 additions and 276 deletions

View File

@ -8158,7 +8158,11 @@ namespace ts {
// Handle catch clause variables
const declaration = symbol.valueDeclaration;
if (isCatchClauseVariableDeclarationOrBindingElement(declaration)) {
return anyType;
const decl = declaration as VariableDeclaration;
if (!decl.type) return anyType;
const type = getTypeOfNode(decl.type);
// an errorType will make `checkTryStatement` issue an error
return isTypeAny(type) || type === unknownType ? type : errorType;
}
// Handle export default expressions
if (isSourceFile(declaration) && isJsonSourceFile(declaration)) {
@ -33403,8 +33407,9 @@ namespace ts {
if (catchClause) {
// Grammar checking
if (catchClause.variableDeclaration) {
if (catchClause.variableDeclaration.type) {
grammarErrorOnFirstToken(catchClause.variableDeclaration.type, Diagnostics.Catch_clause_variable_cannot_have_a_type_annotation);
if (catchClause.variableDeclaration.type && getTypeOfNode(catchClause.variableDeclaration) === errorType) {
grammarErrorOnFirstToken(catchClause.variableDeclaration.type,
Diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified);
}
else if (catchClause.variableDeclaration.initializer) {
grammarErrorOnFirstToken(catchClause.variableDeclaration.initializer, Diagnostics.Catch_clause_variable_cannot_have_an_initializer);

View File

@ -619,7 +619,7 @@
"category": "Error",
"code": 1195
},
"Catch clause variable cannot have a type annotation.": {
"Catch clause variable type annotation must be 'any' or 'unknown' if specified.": {
"category": "Error",
"code": 1196
},

View File

@ -1,9 +1,56 @@
tests/cases/compiler/catchClauseWithTypeAnnotation.ts(2,13): error TS1196: Catch clause variable cannot have a type annotation.
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(17,36): error TS2339: Property 'foo' does not exist on type 'unknown'.
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(18,37): error TS2339: Property 'foo' does not exist on type 'unknown'.
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(19,23): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(20,23): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(29,29): error TS2492: Cannot redeclare identifier 'x' in catch clause.
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(30,29): error TS2403: Subsequent variable declarations must have the same type. Variable 'x' must be of type 'boolean', but here has type 'string'.
==== tests/cases/compiler/catchClauseWithTypeAnnotation.ts (1 errors) ====
try {
} catch (e: any) {
~~~
!!! error TS1196: Catch clause variable cannot have a type annotation.
}
==== tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts (6 errors) ====
type any1 = any;
type unknown1 = unknown;
function fn(x: boolean) {
// no type annotation allowed other than `any` and `unknown`
try { } catch (x) { } // should be OK
try { } catch (x: any) { } // should be OK
try { } catch (x: any1) { } // should be OK
try { } catch (x: unknown) { } // should be OK
try { } catch (x: unknown1) { } // should be OK
try { } catch (x) { x.foo; } // should be OK
try { } catch (x: any) { x.foo; } // should be OK
try { } catch (x: any1) { x.foo; } // should be OK
try { } catch (x: unknown) { console.log(x); } // should be OK
try { } catch (x: unknown1) { console.log(x); } // should be OK
try { } catch (x: unknown) { x.foo; } // error in the body
~~~
!!! error TS2339: Property 'foo' does not exist on type 'unknown'.
try { } catch (x: unknown1) { x.foo; } // error in the body
~~~
!!! error TS2339: Property 'foo' does not exist on type 'unknown'.
try { } catch (x: Error) { } // error in the type
~~~~~
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
try { } catch (x: object) { } // error in the type
~~~~~~
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
try { console.log(); }
// @ts-ignore
catch (e: number) { // e should not be a `number`
console.log(e.toLowerCase());
}
// minor bug: shows that the `catch` argument is skipped when checking scope
try { } catch (x) { let x: string; }
~
!!! error TS2492: Cannot redeclare identifier 'x' in catch clause.
try { } catch (x) { var x: string; }
~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'x' must be of type 'boolean', but here has type 'string'.
!!! related TS6203 tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts:4:13: 'x' was also declared here.
try { } catch (x) { var x: boolean; }
}

View File

@ -1,10 +1,102 @@
//// [catchClauseWithTypeAnnotation.ts]
try {
} catch (e: any) {
}
type any1 = any;
type unknown1 = unknown;
function fn(x: boolean) {
// no type annotation allowed other than `any` and `unknown`
try { } catch (x) { } // should be OK
try { } catch (x: any) { } // should be OK
try { } catch (x: any1) { } // should be OK
try { } catch (x: unknown) { } // should be OK
try { } catch (x: unknown1) { } // should be OK
try { } catch (x) { x.foo; } // should be OK
try { } catch (x: any) { x.foo; } // should be OK
try { } catch (x: any1) { x.foo; } // should be OK
try { } catch (x: unknown) { console.log(x); } // should be OK
try { } catch (x: unknown1) { console.log(x); } // should be OK
try { } catch (x: unknown) { x.foo; } // error in the body
try { } catch (x: unknown1) { x.foo; } // error in the body
try { } catch (x: Error) { } // error in the type
try { } catch (x: object) { } // error in the type
try { console.log(); }
// @ts-ignore
catch (e: number) { // e should not be a `number`
console.log(e.toLowerCase());
}
// minor bug: shows that the `catch` argument is skipped when checking scope
try { } catch (x) { let x: string; }
try { } catch (x) { var x: string; }
try { } catch (x) { var x: boolean; }
}
//// [catchClauseWithTypeAnnotation.js]
try {
}
catch (e) {
function fn(x) {
// no type annotation allowed other than `any` and `unknown`
try { }
catch (x) { } // should be OK
try { }
catch (x) { } // should be OK
try { }
catch (x) { } // should be OK
try { }
catch (x) { } // should be OK
try { }
catch (x) { } // should be OK
try { }
catch (x) {
x.foo;
} // should be OK
try { }
catch (x) {
x.foo;
} // should be OK
try { }
catch (x) {
x.foo;
} // should be OK
try { }
catch (x) {
console.log(x);
} // should be OK
try { }
catch (x) {
console.log(x);
} // should be OK
try { }
catch (x) {
x.foo;
} // error in the body
try { }
catch (x) {
x.foo;
} // error in the body
try { }
catch (x) { } // error in the type
try { }
catch (x) { } // error in the type
try {
console.log();
}
// @ts-ignore
catch (e) { // e should not be a `number`
console.log(e.toLowerCase());
}
// minor bug: shows that the `catch` argument is skipped when checking scope
try { }
catch (x) {
var x_1;
}
try { }
catch (x) {
var x;
}
try { }
catch (x) {
var x;
}
}

View File

@ -1,5 +1,104 @@
=== tests/cases/compiler/catchClauseWithTypeAnnotation.ts ===
try {
} catch (e: any) {
>e : Symbol(e, Decl(catchClauseWithTypeAnnotation.ts, 1, 9))
=== tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts ===
type any1 = any;
>any1 : Symbol(any1, Decl(catchClauseWithTypeAnnotation.ts, 0, 0))
type unknown1 = unknown;
>unknown1 : Symbol(unknown1, Decl(catchClauseWithTypeAnnotation.ts, 0, 16))
function fn(x: boolean) {
>fn : Symbol(fn, Decl(catchClauseWithTypeAnnotation.ts, 1, 24))
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 3, 12), Decl(catchClauseWithTypeAnnotation.ts, 29, 27), Decl(catchClauseWithTypeAnnotation.ts, 30, 27))
// no type annotation allowed other than `any` and `unknown`
try { } catch (x) { } // should be OK
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 6, 19))
try { } catch (x: any) { } // should be OK
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 7, 19))
try { } catch (x: any1) { } // should be OK
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 8, 19))
>any1 : Symbol(any1, Decl(catchClauseWithTypeAnnotation.ts, 0, 0))
try { } catch (x: unknown) { } // should be OK
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 9, 19))
try { } catch (x: unknown1) { } // should be OK
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 10, 19))
>unknown1 : Symbol(unknown1, Decl(catchClauseWithTypeAnnotation.ts, 0, 16))
try { } catch (x) { x.foo; } // should be OK
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 11, 19))
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 11, 19))
try { } catch (x: any) { x.foo; } // should be OK
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 12, 19))
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 12, 19))
try { } catch (x: any1) { x.foo; } // should be OK
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 13, 19))
>any1 : Symbol(any1, Decl(catchClauseWithTypeAnnotation.ts, 0, 0))
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 13, 19))
try { } catch (x: unknown) { console.log(x); } // should be OK
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 14, 19))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 14, 19))
try { } catch (x: unknown1) { console.log(x); } // should be OK
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 15, 19))
>unknown1 : Symbol(unknown1, Decl(catchClauseWithTypeAnnotation.ts, 0, 16))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 15, 19))
try { } catch (x: unknown) { x.foo; } // error in the body
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 16, 19))
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 16, 19))
try { } catch (x: unknown1) { x.foo; } // error in the body
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 17, 19))
>unknown1 : Symbol(unknown1, Decl(catchClauseWithTypeAnnotation.ts, 0, 16))
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 17, 19))
try { } catch (x: Error) { } // error in the type
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 18, 19))
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
try { } catch (x: object) { } // error in the type
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 19, 19))
try { console.log(); }
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
// @ts-ignore
catch (e: number) { // e should not be a `number`
>e : Symbol(e, Decl(catchClauseWithTypeAnnotation.ts, 23, 11))
console.log(e.toLowerCase());
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>e : Symbol(e, Decl(catchClauseWithTypeAnnotation.ts, 23, 11))
}
// minor bug: shows that the `catch` argument is skipped when checking scope
try { } catch (x) { let x: string; }
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 28, 19))
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 28, 27))
try { } catch (x) { var x: string; }
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 29, 19))
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 3, 12), Decl(catchClauseWithTypeAnnotation.ts, 29, 27), Decl(catchClauseWithTypeAnnotation.ts, 30, 27))
try { } catch (x) { var x: boolean; }
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 30, 19))
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 3, 12), Decl(catchClauseWithTypeAnnotation.ts, 29, 27), Decl(catchClauseWithTypeAnnotation.ts, 30, 27))
}

View File

@ -1,5 +1,115 @@
=== tests/cases/compiler/catchClauseWithTypeAnnotation.ts ===
try {
} catch (e: any) {
=== tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts ===
type any1 = any;
>any1 : any
type unknown1 = unknown;
>unknown1 : unknown
function fn(x: boolean) {
>fn : (x: boolean) => void
>x : boolean
// no type annotation allowed other than `any` and `unknown`
try { } catch (x) { } // should be OK
>x : any
try { } catch (x: any) { } // should be OK
>x : any
try { } catch (x: any1) { } // should be OK
>x : any
try { } catch (x: unknown) { } // should be OK
>x : unknown
try { } catch (x: unknown1) { } // should be OK
>x : unknown
try { } catch (x) { x.foo; } // should be OK
>x : any
>x.foo : any
>x : any
>foo : any
try { } catch (x: any) { x.foo; } // should be OK
>x : any
>x.foo : any
>x : any
>foo : any
try { } catch (x: any1) { x.foo; } // should be OK
>x : any
>x.foo : any
>x : any
>foo : any
try { } catch (x: unknown) { console.log(x); } // should be OK
>x : unknown
>console.log(x) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>x : unknown
try { } catch (x: unknown1) { console.log(x); } // should be OK
>x : unknown
>console.log(x) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>x : unknown
try { } catch (x: unknown) { x.foo; } // error in the body
>x : unknown
>x.foo : any
>x : unknown
>foo : any
try { } catch (x: unknown1) { x.foo; } // error in the body
>x : unknown
>x.foo : any
>x : unknown
>foo : any
try { } catch (x: Error) { } // error in the type
>x : any
try { } catch (x: object) { } // error in the type
>x : any
try { console.log(); }
>console.log() : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
// @ts-ignore
catch (e: number) { // e should not be a `number`
>e : any
console.log(e.toLowerCase());
>console.log(e.toLowerCase()) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>e.toLowerCase() : any
>e.toLowerCase : any
>e : any
>toLowerCase : any
}
// minor bug: shows that the `catch` argument is skipped when checking scope
try { } catch (x) { let x: string; }
>x : any
>x : string
try { } catch (x) { var x: string; }
>x : any
>x : boolean
try { } catch (x) { var x: boolean; }
>x : any
>x : boolean
}

View File

@ -1,25 +1,44 @@
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(8,23): error TS1196: Catch clause variable cannot have a type annotation.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(9,23): error TS1196: Catch clause variable cannot have a type annotation.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(10,23): error TS1196: Catch clause variable cannot have a type annotation.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(2,5): error TS1005: 'try' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(6,12): error TS1005: 'finally' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(10,5): error TS1005: 'try' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(11,5): error TS1005: 'try' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(15,5): error TS1005: 'try' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(17,5): error TS1005: 'try' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(19,20): error TS1003: Identifier expected.
==== tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts (3 errors) ====
==== tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts (7 errors) ====
function fn() {
try {
} catch (x) {
var x: string; // ensure x is 'Any'
}
catch(x) { } // error missing try
~~~~~
!!! error TS1005: 'try' expected.
// no type annotation allowed
try { } catch (z: any) { }
~~~
!!! error TS1196: Catch clause variable cannot have a type annotation.
try { } catch (a: number) { }
~~~~~~
!!! error TS1196: Catch clause variable cannot have a type annotation.
try { } catch (y: string) { }
~~~~~~
!!! error TS1196: Catch clause variable cannot have a type annotation.
finally { } // potential error; can be absorbed by the 'catch'
try { }; // error missing finally
~
!!! error TS1005: 'finally' expected.
}
function fn2() {
finally { } // error missing try
~~~~~~~
!!! error TS1005: 'try' expected.
catch (x) { } // error missing try
~~~~~
!!! error TS1005: 'try' expected.
try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
finally { } // error missing try
~~~~~~~
!!! error TS1005: 'try' expected.
catch (x) { } // error missing try
~~~~~
!!! error TS1005: 'try' expected.
try { } catch () { } // error missing catch binding
~
!!! error TS1003: Identifier expected.
}

View File

@ -1,30 +1,51 @@
//// [invalidTryStatements.ts]
function fn() {
try {
} catch (x) {
var x: string; // ensure x is 'Any'
}
catch(x) { } // error missing try
// no type annotation allowed
try { } catch (z: any) { }
try { } catch (a: number) { }
try { } catch (y: string) { }
finally { } // potential error; can be absorbed by the 'catch'
try { }; // error missing finally
}
function fn2() {
finally { } // error missing try
catch (x) { } // error missing try
try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
finally { } // error missing try
catch (x) { } // error missing try
try { } catch () { } // error missing catch binding
}
//// [invalidTryStatements.js]
function fn() {
try {
}
catch (x) {
var x; // ensure x is 'Any'
}
// no type annotation allowed
catch (x) { } // error missing try
finally { } // potential error; can be absorbed by the 'catch'
try { }
catch (z) { }
try { }
catch (a) { }
try { }
catch (y) { }
finally { // error missing finally
} // error missing finally
; // error missing finally
}
function fn2() {
try {
}
finally { } // error missing try
try {
}
catch (x) { } // error missing try
try { }
finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
try {
}
finally { } // error missing try
try {
}
catch (x) { } // error missing try
try { }
catch () { } // error missing catch binding
}

View File

@ -2,23 +2,28 @@
function fn() {
>fn : Symbol(fn, Decl(invalidTryStatements.ts, 0, 0))
try {
} catch (x) {
>x : Symbol(x, Decl(invalidTryStatements.ts, 2, 13))
catch(x) { } // error missing try
>x : Symbol(x, Decl(invalidTryStatements.ts, 1, 10))
var x: string; // ensure x is 'Any'
>x : Symbol(x, Decl(invalidTryStatements.ts, 3, 11))
}
finally { } // potential error; can be absorbed by the 'catch'
// no type annotation allowed
try { } catch (z: any) { }
>z : Symbol(z, Decl(invalidTryStatements.ts, 7, 19))
try { } catch (a: number) { }
>a : Symbol(a, Decl(invalidTryStatements.ts, 8, 19))
try { } catch (y: string) { }
>y : Symbol(y, Decl(invalidTryStatements.ts, 9, 19))
try { }; // error missing finally
}
function fn2() {
>fn2 : Symbol(fn2, Decl(invalidTryStatements.ts, 6, 1))
finally { } // error missing try
catch (x) { } // error missing try
>x : Symbol(x, Decl(invalidTryStatements.ts, 10, 11))
try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
finally { } // error missing try
catch (x) { } // error missing try
>x : Symbol(x, Decl(invalidTryStatements.ts, 16, 11))
try { } catch () { } // error missing catch binding
> : Symbol((Missing), Decl(invalidTryStatements.ts, 18, 19))
}

View File

@ -2,23 +2,28 @@
function fn() {
>fn : () => void
try {
} catch (x) {
catch(x) { } // error missing try
>x : any
var x: string; // ensure x is 'Any'
>x : string
}
finally { } // potential error; can be absorbed by the 'catch'
// no type annotation allowed
try { } catch (z: any) { }
>z : any
try { } catch (a: number) { }
>a : any
try { } catch (y: string) { }
>y : any
try { }; // error missing finally
}
function fn2() {
>fn2 : () => void
finally { } // error missing try
catch (x) { } // error missing try
>x : any
try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
finally { } // error missing try
catch (x) { } // error missing try
>x : any
try { } catch () { } // error missing catch binding
> : any
}

View File

@ -1,44 +0,0 @@
tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(2,5): error TS1005: 'try' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(6,12): error TS1005: 'finally' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(10,5): error TS1005: 'try' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(11,5): error TS1005: 'try' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(15,5): error TS1005: 'try' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(17,5): error TS1005: 'try' expected.
tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(19,20): error TS1003: Identifier expected.
==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (7 errors) ====
function fn() {
catch(x) { } // error missing try
~~~~~
!!! error TS1005: 'try' expected.
finally { } // potential error; can be absorbed by the 'catch'
try { }; // error missing finally
~
!!! error TS1005: 'finally' expected.
}
function fn2() {
finally { } // error missing try
~~~~~~~
!!! error TS1005: 'try' expected.
catch (x) { } // error missing try
~~~~~
!!! error TS1005: 'try' expected.
try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
finally { } // error missing try
~~~~~~~
!!! error TS1005: 'try' expected.
catch (x) { } // error missing try
~~~~~
!!! error TS1005: 'try' expected.
try { } catch () { } // error missing catch binding
~
!!! error TS1003: Identifier expected.
}

View File

@ -1,51 +0,0 @@
//// [invalidTryStatements2.ts]
function fn() {
catch(x) { } // error missing try
finally { } // potential error; can be absorbed by the 'catch'
try { }; // error missing finally
}
function fn2() {
finally { } // error missing try
catch (x) { } // error missing try
try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
finally { } // error missing try
catch (x) { } // error missing try
try { } catch () { } // error missing catch binding
}
//// [invalidTryStatements2.js]
function fn() {
try {
}
catch (x) { } // error missing try
finally { } // potential error; can be absorbed by the 'catch'
try { }
finally { // error missing finally
} // error missing finally
; // error missing finally
}
function fn2() {
try {
}
finally { } // error missing try
try {
}
catch (x) { } // error missing try
try { }
finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
try {
}
finally { } // error missing try
try {
}
catch (x) { } // error missing try
try { }
catch () { } // error missing catch binding
}

View File

@ -1,29 +0,0 @@
=== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts ===
function fn() {
>fn : Symbol(fn, Decl(invalidTryStatements2.ts, 0, 0))
catch(x) { } // error missing try
>x : Symbol(x, Decl(invalidTryStatements2.ts, 1, 10))
finally { } // potential error; can be absorbed by the 'catch'
try { }; // error missing finally
}
function fn2() {
>fn2 : Symbol(fn2, Decl(invalidTryStatements2.ts, 6, 1))
finally { } // error missing try
catch (x) { } // error missing try
>x : Symbol(x, Decl(invalidTryStatements2.ts, 10, 11))
try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
finally { } // error missing try
catch (x) { } // error missing try
>x : Symbol(x, Decl(invalidTryStatements2.ts, 16, 11))
try { } catch () { } // error missing catch binding
> : Symbol((Missing), Decl(invalidTryStatements2.ts, 18, 19))
}

View File

@ -1,29 +0,0 @@
=== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts ===
function fn() {
>fn : () => void
catch(x) { } // error missing try
>x : any
finally { } // potential error; can be absorbed by the 'catch'
try { }; // error missing finally
}
function fn2() {
>fn2 : () => void
finally { } // error missing try
catch (x) { } // error missing try
>x : any
try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
finally { } // error missing try
catch (x) { } // error missing try
>x : any
try { } catch () { } // error missing catch binding
> : any
}

View File

@ -1,10 +1,10 @@
tests/cases/conformance/parser/ecmascript5/CatchClauses/parserCatchClauseWithTypeAnnotation1.ts(2,13): error TS1196: Catch clause variable cannot have a type annotation.
tests/cases/conformance/parser/ecmascript5/CatchClauses/parserCatchClauseWithTypeAnnotation1.ts(2,13): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
==== tests/cases/conformance/parser/ecmascript5/CatchClauses/parserCatchClauseWithTypeAnnotation1.ts (1 errors) ====
try {
} catch (e: Error) {
~~~~~
!!! error TS1196: Catch clause variable cannot have a type annotation.
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
}

View File

@ -1,3 +0,0 @@
try {
} catch (e: any) {
}

View File

@ -0,0 +1,33 @@
type any1 = any;
type unknown1 = unknown;
function fn(x: boolean) {
// no type annotation allowed other than `any` and `unknown`
try { } catch (x) { } // should be OK
try { } catch (x: any) { } // should be OK
try { } catch (x: any1) { } // should be OK
try { } catch (x: unknown) { } // should be OK
try { } catch (x: unknown1) { } // should be OK
try { } catch (x) { x.foo; } // should be OK
try { } catch (x: any) { x.foo; } // should be OK
try { } catch (x: any1) { x.foo; } // should be OK
try { } catch (x: unknown) { console.log(x); } // should be OK
try { } catch (x: unknown1) { console.log(x); } // should be OK
try { } catch (x: unknown) { x.foo; } // error in the body
try { } catch (x: unknown1) { x.foo; } // error in the body
try { } catch (x: Error) { } // error in the type
try { } catch (x: object) { } // error in the type
try { console.log(); }
// @ts-ignore
catch (e: number) { // e should not be a `number`
console.log(e.toLowerCase());
}
// minor bug: shows that the `catch` argument is skipped when checking scope
try { } catch (x) { let x: string; }
try { } catch (x) { var x: string; }
try { } catch (x) { var x: boolean; }
}

View File

@ -1,12 +1,20 @@
function fn() {
try {
} catch (x) {
var x: string; // ensure x is 'Any'
}
catch(x) { } // error missing try
// no type annotation allowed
try { } catch (z: any) { }
try { } catch (a: number) { }
try { } catch (y: string) { }
finally { } // potential error; can be absorbed by the 'catch'
try { }; // error missing finally
}
function fn2() {
finally { } // error missing try
catch (x) { } // error missing try
try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
finally { } // error missing try
catch (x) { } // error missing try
try { } catch () { } // error missing catch binding
}

View File

@ -1,20 +0,0 @@
function fn() {
catch(x) { } // error missing try
finally { } // potential error; can be absorbed by the 'catch'
try { }; // error missing finally
}
function fn2() {
finally { } // error missing try
catch (x) { } // error missing try
try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below
finally { } // error missing try
catch (x) { } // error missing try
try { } catch () { } // error missing catch binding
}