Skip to content

Commit 9386f12

Browse files
committed
Allow arbitrary catch clause type annotations
1 parent c7a4c13 commit 9386f12

8 files changed

+31
-62
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10206,11 +10206,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1020610206

1020710207
// Use type from type annotation if one is present
1020810208
const declaredType = tryGetTypeFromEffectiveTypeNode(declaration);
10209-
if (isCatchClauseVariableDeclarationOrBindingElement(declaration)) {
10210-
if (declaredType) {
10211-
// If the catch clause is explicitly annotated with any or unknown, accept it, otherwise error.
10212-
return isTypeAny(declaredType) || declaredType === unknownType ? declaredType : errorType;
10213-
}
10209+
if (!declaredType && isCatchClauseVariableDeclarationOrBindingElement(declaration)) {
1021410210
// If the catch clause is not explicitly annotated, treat it as though it were explicitly
1021510211
// annotated with unknown or any, depending on useUnknownInCatchVariables.
1021610212
return useUnknownInCatchVariables ? unknownType : anyType;
@@ -41179,14 +41175,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4117941175
if (catchClause.variableDeclaration) {
4118041176
const declaration = catchClause.variableDeclaration;
4118141177
checkVariableLikeDeclaration(declaration);
41182-
const typeNode = getEffectiveTypeAnnotationNode(declaration);
41183-
if (typeNode) {
41184-
const type = getTypeFromTypeNode(typeNode);
41185-
if (type && !(type.flags & TypeFlags.AnyOrUnknown)) {
41186-
grammarErrorOnFirstToken(typeNode, Diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified);
41187-
}
41188-
}
41189-
else if (declaration.initializer) {
41178+
if (declaration.initializer) {
4119041179
grammarErrorOnFirstToken(declaration.initializer, Diagnostics.Catch_clause_variable_cannot_have_an_initializer);
4119141180
}
4119241181
else {

src/compiler/diagnosticMessages.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -607,10 +607,6 @@
607607
"category": "Error",
608608
"code": 1195
609609
},
610-
"Catch clause variable type annotation must be 'any' or 'unknown' if specified.": {
611-
"category": "Error",
612-
"code": 1196
613-
},
614610
"Catch clause variable cannot have an initializer.": {
615611
"category": "Error",
616612
"code": 1197

tests/baselines/reference/catchClauseWithTypeAnnotation.errors.txt

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(17,36): error TS2339: Property 'foo' does not exist on type 'unknown'.
22
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(18,37): error TS2339: Property 'foo' does not exist on type 'unknown'.
3-
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(19,23): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
4-
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(20,23): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
3+
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(25,23): error TS2339: Property 'toLowerCase' does not exist on type 'number'.
54
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(29,29): error TS2492: Cannot redeclare identifier 'x' in catch clause.
65
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'.
76
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(36,22): error TS2339: Property 'x' does not exist on type '{}'.
87
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(37,22): error TS2339: Property 'x' does not exist on type '{}'.
9-
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(38,27): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
10-
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(39,27): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
8+
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(38,22): error TS2339: Property 'x' does not exist on type '{}'.
9+
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(39,22): error TS2339: Property 'x' does not exist on type 'Error'.
1110

1211

13-
==== tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts (10 errors) ====
12+
==== tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts (9 errors) ====
1413
type any1 = any;
1514
type unknown1 = unknown;
1615

@@ -34,16 +33,14 @@ tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.t
3433
~~~
3534
!!! error TS2339: Property 'foo' does not exist on type 'unknown'.
3635
try { } catch (x: Error) { } // error in the type
37-
~~~~~
38-
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
3936
try { } catch (x: object) { } // error in the type
40-
~~~~~~
41-
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
4237

4338
try { console.log(); }
4439
// @ts-ignore
4540
catch (e: number) { // e should not be a `number`
4641
console.log(e.toLowerCase());
42+
~~~~~~~~~~~
43+
!!! error TS2339: Property 'toLowerCase' does not exist on type 'number'.
4744
}
4845

4946
// minor bug: shows that the `catch` argument is skipped when checking scope
@@ -66,10 +63,10 @@ tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.t
6663
~
6764
!!! error TS2339: Property 'x' does not exist on type '{}'.
6865
try { } catch ({ x }: object) { } // error in the type
69-
~~~~~~
70-
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
66+
~
67+
!!! error TS2339: Property 'x' does not exist on type '{}'.
7168
try { } catch ({ x }: Error) { } // error in the type
72-
~~~~~
73-
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
69+
~
70+
!!! error TS2339: Property 'x' does not exist on type 'Error'.
7471
}
7572

tests/baselines/reference/catchClauseWithTypeAnnotation.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ function fn(x: boolean) {
7272
>foo : any
7373

7474
try { } catch (x: Error) { } // error in the type
75-
>x : any
75+
>x : Error
7676

7777
try { } catch (x: object) { } // error in the type
78-
>x : any
78+
>x : object
7979

8080
try { console.log(); }
8181
>console.log() : void
@@ -85,7 +85,7 @@ function fn(x: boolean) {
8585

8686
// @ts-ignore
8787
catch (e: number) { // e should not be a `number`
88-
>e : any
88+
>e : number
8989

9090
console.log(e.toLowerCase());
9191
>console.log(e.toLowerCase()) : void
@@ -94,7 +94,7 @@ function fn(x: boolean) {
9494
>log : (...data: any[]) => void
9595
>e.toLowerCase() : any
9696
>e.toLowerCase : any
97-
>e : any
97+
>e : number
9898
>toLowerCase : any
9999
}
100100

tests/baselines/reference/jsdocCatchClauseWithTypeAnnotation.errors.txt

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
tests/cases/conformance/jsdoc/foo.js(20,54): error TS2339: Property 'foo' does not exist on type 'unknown'.
22
tests/cases/conformance/jsdoc/foo.js(21,54): error TS2339: Property 'foo' does not exist on type 'unknown'.
3-
tests/cases/conformance/jsdoc/foo.js(22,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
4-
tests/cases/conformance/jsdoc/foo.js(23,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
3+
tests/cases/conformance/jsdoc/foo.js(28,25): error TS2339: Property 'toLowerCase' does not exist on type 'number'.
54
tests/cases/conformance/jsdoc/foo.js(35,7): error TS2492: Cannot redeclare identifier 'err' in catch clause.
65
tests/cases/conformance/jsdoc/foo.js(46,45): error TS2339: Property 'x' does not exist on type '{}'.
76
tests/cases/conformance/jsdoc/foo.js(47,45): error TS2339: Property 'x' does not exist on type '{}'.
8-
tests/cases/conformance/jsdoc/foo.js(48,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
9-
tests/cases/conformance/jsdoc/foo.js(49,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
7+
tests/cases/conformance/jsdoc/foo.js(48,43): error TS2339: Property 'x' does not exist on type 'Error'.
8+
tests/cases/conformance/jsdoc/foo.js(49,44): error TS2339: Property 'x' does not exist on type '{}'.
109

1110

12-
==== tests/cases/conformance/jsdoc/foo.js (9 errors) ====
11+
==== tests/cases/conformance/jsdoc/foo.js (8 errors) ====
1312
/**
1413
* @typedef {any} Any
1514
*/
@@ -36,16 +35,14 @@ tests/cases/conformance/jsdoc/foo.js(49,31): error TS1196: Catch clause variable
3635
~~~
3736
!!! error TS2339: Property 'foo' does not exist on type 'unknown'.
3837
try { } catch (/** @type {Error} */ err) { } // error in the type
39-
~~~~~
40-
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
4138
try { } catch (/** @type {object} */ err) { } // error in the type
42-
~~~~~~
43-
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
4439

4540
try { console.log(); }
4641
// @ts-ignore
4742
catch (/** @type {number} */ err) { // e should not be a `number`
4843
console.log(err.toLowerCase());
44+
~~~~~~~~~~~
45+
!!! error TS2339: Property 'toLowerCase' does not exist on type 'number'.
4946
}
5047

5148
// minor bug: shows that the `catch` argument is skipped when checking scope
@@ -72,10 +69,10 @@ tests/cases/conformance/jsdoc/foo.js(49,31): error TS1196: Catch clause variable
7269
~
7370
!!! error TS2339: Property 'x' does not exist on type '{}'.
7471
try { } catch (/** @type {Error} */ { x }) { } // error in the type
75-
~~~~~
76-
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
72+
~
73+
!!! error TS2339: Property 'x' does not exist on type 'Error'.
7774
try { } catch (/** @type {object} */ { x }) { } // error in the type
78-
~~~~~~
79-
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
75+
~
76+
!!! error TS2339: Property 'x' does not exist on type '{}'.
8077
}
8178

tests/baselines/reference/jsdocCatchClauseWithTypeAnnotation.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ function fn() {
7272
>foo : any
7373

7474
try { } catch (/** @type {Error} */ err) { } // error in the type
75-
>err : any
75+
>err : Error
7676

7777
try { } catch (/** @type {object} */ err) { } // error in the type
78-
>err : any
78+
>err : object
7979

8080
try { console.log(); }
8181
>console.log() : void
@@ -85,7 +85,7 @@ function fn() {
8585

8686
// @ts-ignore
8787
catch (/** @type {number} */ err) { // e should not be a `number`
88-
>err : any
88+
>err : number
8989

9090
console.log(err.toLowerCase());
9191
>console.log(err.toLowerCase()) : void
@@ -94,7 +94,7 @@ function fn() {
9494
>log : (...data: any[]) => void
9595
>err.toLowerCase() : any
9696
>err.toLowerCase : any
97-
>err : any
97+
>err : number
9898
>toLowerCase : any
9999
}
100100

tests/baselines/reference/parserCatchClauseWithTypeAnnotation1.errors.txt

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
=== tests/cases/conformance/parser/ecmascript5/CatchClauses/parserCatchClauseWithTypeAnnotation1.ts ===
22
try {
33
} catch (e: Error) {
4-
>e : any
4+
>e : Error
55
}
66

0 commit comments

Comments
 (0)