Skip to content

Commit 40964a3

Browse files
committed
fix(47383): throw an error on catch variable with unknown type
1 parent 935c05c commit 40964a3

File tree

36 files changed

+633
-26
lines changed

36 files changed

+633
-26
lines changed

Diff for: src/compiler/checker.ts

+6
Original file line numberDiff line numberDiff line change
@@ -9346,6 +9346,12 @@ namespace ts {
93469346
Debug.assertIsDefined(symbol.valueDeclaration);
93479347
const declaration = symbol.valueDeclaration;
93489348
if (isCatchClauseVariableDeclarationOrBindingElement(declaration)) {
9349+
if (isBindingElement(declaration)) {
9350+
const typeNode = getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration));
9351+
return typeNode && getTypeOfNode(typeNode) === unknownType || useUnknownInCatchVariables
9352+
? getBindingElementTypeFromParentType(declaration, unknownType)
9353+
: anyType;
9354+
}
93499355
const typeNode = getEffectiveTypeAnnotationNode(declaration);
93509356
if (typeNode === undefined) {
93519357
return useUnknownInCatchVariables ? unknownType : anyType;

Diff for: tests/baselines/reference/catchClauseWithTypeAnnotation.errors.txt

+9-3
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.t
44
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(20,23): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
55
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(29,29): error TS2492: Cannot redeclare identifier 'x' in catch clause.
66
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'.
7+
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(36,22): error TS2339: Property 'x' does not exist on type '{}'.
8+
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(37,22): error TS2339: Property 'x' does not exist on type '{}'.
79
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(38,27): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
810
tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts(39,27): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
911

1012

11-
==== tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts (8 errors) ====
13+
==== tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.ts (10 errors) ====
1214
type any1 = any;
1315
type unknown1 = unknown;
1416

@@ -57,8 +59,12 @@ tests/cases/conformance/statements/tryStatements/catchClauseWithTypeAnnotation.t
5759
try { } catch ({ x }) { } // should be OK
5860
try { } catch ({ x }: any) { x.foo; } // should be OK
5961
try { } catch ({ x }: any1) { x.foo;} // should be OK
60-
try { } catch ({ x }: unknown) { console.log(x); } // should be OK
61-
try { } catch ({ x }: unknown1) { console.log(x); } // should be OK
62+
try { } catch ({ x }: unknown) { console.log(x); } // error in the type
63+
~
64+
!!! error TS2339: Property 'x' does not exist on type '{}'.
65+
try { } catch ({ x }: unknown1) { console.log(x); } // error in the type
66+
~
67+
!!! error TS2339: Property 'x' does not exist on type '{}'.
6268
try { } catch ({ x }: object) { } // error in the type
6369
~~~~~~
6470
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.

Diff for: tests/baselines/reference/catchClauseWithTypeAnnotation.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ function fn(x: boolean) {
3434
try { } catch ({ x }) { } // should be OK
3535
try { } catch ({ x }: any) { x.foo; } // should be OK
3636
try { } catch ({ x }: any1) { x.foo;} // should be OK
37-
try { } catch ({ x }: unknown) { console.log(x); } // should be OK
38-
try { } catch ({ x }: unknown1) { console.log(x); } // should be OK
37+
try { } catch ({ x }: unknown) { console.log(x); } // error in the type
38+
try { } catch ({ x }: unknown1) { console.log(x); } // error in the type
3939
try { } catch ({ x }: object) { } // error in the type
4040
try { } catch ({ x }: Error) { } // error in the type
4141
}
@@ -124,12 +124,12 @@ function fn(x) {
124124
catch (_d) {
125125
var x_5 = _d.x;
126126
console.log(x_5);
127-
} // should be OK
127+
} // error in the type
128128
try { }
129129
catch (_e) {
130130
var x_6 = _e.x;
131131
console.log(x_6);
132-
} // should be OK
132+
} // error in the type
133133
try { }
134134
catch (_f) {
135135
var x_7 = _f.x;

Diff for: tests/baselines/reference/catchClauseWithTypeAnnotation.symbols

+2-2
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,14 @@ function fn(x: boolean) {
112112
>any1 : Symbol(any1, Decl(catchClauseWithTypeAnnotation.ts, 0, 0))
113113
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 34, 20))
114114

115-
try { } catch ({ x }: unknown) { console.log(x); } // should be OK
115+
try { } catch ({ x }: unknown) { console.log(x); } // error in the type
116116
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 35, 20))
117117
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
118118
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
119119
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
120120
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 35, 20))
121121

122-
try { } catch ({ x }: unknown1) { console.log(x); } // should be OK
122+
try { } catch ({ x }: unknown1) { console.log(x); } // error in the type
123123
>x : Symbol(x, Decl(catchClauseWithTypeAnnotation.ts, 36, 20))
124124
>unknown1 : Symbol(unknown1, Decl(catchClauseWithTypeAnnotation.ts, 0, 16))
125125
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))

Diff for: tests/baselines/reference/catchClauseWithTypeAnnotation.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,15 @@ function fn(x: boolean) {
126126
>x : any
127127
>foo : any
128128

129-
try { } catch ({ x }: unknown) { console.log(x); } // should be OK
129+
try { } catch ({ x }: unknown) { console.log(x); } // error in the type
130130
>x : any
131131
>console.log(x) : void
132132
>console.log : (...data: any[]) => void
133133
>console : Console
134134
>log : (...data: any[]) => void
135135
>x : any
136136

137-
try { } catch ({ x }: unknown1) { console.log(x); } // should be OK
137+
try { } catch ({ x }: unknown1) { console.log(x); } // error in the type
138138
>x : any
139139
>console.log(x) : void
140140
>console.log : (...data: any[]) => void

Diff for: tests/baselines/reference/jsdocCatchClauseWithTypeAnnotation.errors.txt

+9-3
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ tests/cases/conformance/jsdoc/foo.js(21,54): error TS2339: Property 'foo' does n
33
tests/cases/conformance/jsdoc/foo.js(22,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
44
tests/cases/conformance/jsdoc/foo.js(23,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
55
tests/cases/conformance/jsdoc/foo.js(35,7): error TS2492: Cannot redeclare identifier 'err' in catch clause.
6+
tests/cases/conformance/jsdoc/foo.js(46,45): error TS2339: Property 'x' does not exist on type '{}'.
7+
tests/cases/conformance/jsdoc/foo.js(47,45): error TS2339: Property 'x' does not exist on type '{}'.
68
tests/cases/conformance/jsdoc/foo.js(48,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
79
tests/cases/conformance/jsdoc/foo.js(49,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
810

911

10-
==== tests/cases/conformance/jsdoc/foo.js (7 errors) ====
12+
==== tests/cases/conformance/jsdoc/foo.js (9 errors) ====
1113
/**
1214
* @typedef {any} Any
1315
*/
@@ -63,8 +65,12 @@ tests/cases/conformance/jsdoc/foo.js(49,31): error TS1196: Catch clause variable
6365
try { } catch ({ x }) { } // should be OK
6466
try { } catch (/** @type {any} */ { x }) { x.foo; } // should be OK
6567
try { } catch (/** @type {Any} */ { x }) { x.foo;} // should be OK
66-
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // should be OK
67-
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // should be OK
68+
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // error in the type
69+
~
70+
!!! error TS2339: Property 'x' does not exist on type '{}'.
71+
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // error in the type
72+
~
73+
!!! error TS2339: Property 'x' does not exist on type '{}'.
6874
try { } catch (/** @type {Error} */ { x }) { } // error in the type
6975
~~~~~
7076
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.

Diff for: tests/baselines/reference/jsdocCatchClauseWithTypeAnnotation.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ function fn() {
4444
try { } catch ({ x }) { } // should be OK
4545
try { } catch (/** @type {any} */ { x }) { x.foo; } // should be OK
4646
try { } catch (/** @type {Any} */ { x }) { x.foo;} // should be OK
47-
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // should be OK
48-
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // should be OK
47+
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // error in the type
48+
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // error in the type
4949
try { } catch (/** @type {Error} */ { x }) { } // error in the type
5050
try { } catch (/** @type {object} */ { x }) { } // error in the type
5151
}
@@ -132,11 +132,11 @@ function fn() {
132132
try { }
133133
catch ( /** @type {unknown} */{ x }) {
134134
console.log(x);
135-
} // should be OK
135+
} // error in the type
136136
try { }
137137
catch ( /** @type {Unknown} */{ x }) {
138138
console.log(x);
139-
} // should be OK
139+
} // error in the type
140140
try { }
141141
catch ( /** @type {Error} */{ x }) { } // error in the type
142142
try { }

Diff for: tests/baselines/reference/jsdocCatchClauseWithTypeAnnotation.symbols

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,14 @@ function fn() {
110110
>x : Symbol(x, Decl(foo.js, 44, 39))
111111
>x : Symbol(x, Decl(foo.js, 44, 39))
112112

113-
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // should be OK
113+
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // error in the type
114114
>x : Symbol(x, Decl(foo.js, 45, 43))
115115
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
116116
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
117117
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
118118
>x : Symbol(x, Decl(foo.js, 45, 43))
119119

120-
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // should be OK
120+
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // error in the type
121121
>x : Symbol(x, Decl(foo.js, 46, 43))
122122
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
123123
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))

Diff for: tests/baselines/reference/jsdocCatchClauseWithTypeAnnotation.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,15 @@ function fn() {
131131
>x : any
132132
>foo : any
133133

134-
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // should be OK
134+
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // error in the type
135135
>x : any
136136
>console.log(x) : void
137137
>console.log : (...data: any[]) => void
138138
>console : Console
139139
>log : (...data: any[]) => void
140140
>x : any
141141

142-
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // should be OK
142+
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // error in the type
143143
>x : any
144144
>console.log(x) : void
145145
>console.log : (...data: any[]) => void
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
tests/cases/compiler/useUnknownInCatchVariables02.ts(4,10): error TS2339: Property 'name' does not exist on type '{}'.
2+
tests/cases/compiler/useUnknownInCatchVariables02.ts(11,10): error TS2339: Property 'name' does not exist on type '{}'.
3+
4+
5+
==== tests/cases/compiler/useUnknownInCatchVariables02.ts (2 errors) ====
6+
try {
7+
// ...
8+
}
9+
catch ({ name }) {
10+
~~~~
11+
!!! error TS2339: Property 'name' does not exist on type '{}'.
12+
name;
13+
}
14+
15+
try {
16+
// ...
17+
}
18+
catch ({ name }: unknown) {
19+
~~~~
20+
!!! error TS2339: Property 'name' does not exist on type '{}'.
21+
name;
22+
}
23+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//// [useUnknownInCatchVariables02.ts]
2+
try {
3+
// ...
4+
}
5+
catch ({ name }) {
6+
name;
7+
}
8+
9+
try {
10+
// ...
11+
}
12+
catch ({ name }: unknown) {
13+
name;
14+
}
15+
16+
17+
//// [useUnknownInCatchVariables02.js]
18+
try {
19+
// ...
20+
}
21+
catch (_a) {
22+
var name = _a.name;
23+
name;
24+
}
25+
try {
26+
// ...
27+
}
28+
catch (_b) {
29+
var name = _b.name;
30+
name;
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
=== tests/cases/compiler/useUnknownInCatchVariables02.ts ===
2+
try {
3+
// ...
4+
}
5+
catch ({ name }) {
6+
>name : Symbol(name, Decl(useUnknownInCatchVariables02.ts, 3, 8))
7+
8+
name;
9+
>name : Symbol(name, Decl(useUnknownInCatchVariables02.ts, 3, 8))
10+
}
11+
12+
try {
13+
// ...
14+
}
15+
catch ({ name }: unknown) {
16+
>name : Symbol(name, Decl(useUnknownInCatchVariables02.ts, 10, 8))
17+
18+
name;
19+
>name : Symbol(name, Decl(useUnknownInCatchVariables02.ts, 10, 8))
20+
}
21+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
=== tests/cases/compiler/useUnknownInCatchVariables02.ts ===
2+
try {
3+
// ...
4+
}
5+
catch ({ name }) {
6+
>name : any
7+
8+
name;
9+
>name : any
10+
}
11+
12+
try {
13+
// ...
14+
}
15+
catch ({ name }: unknown) {
16+
>name : any
17+
18+
name;
19+
>name : any
20+
}
21+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
tests/cases/compiler/useUnknownInCatchVariables02.ts(11,10): error TS2339: Property 'name' does not exist on type '{}'.
2+
3+
4+
==== tests/cases/compiler/useUnknownInCatchVariables02.ts (1 errors) ====
5+
try {
6+
// ...
7+
}
8+
catch ({ name }) {
9+
name;
10+
}
11+
12+
try {
13+
// ...
14+
}
15+
catch ({ name }: unknown) {
16+
~~~~
17+
!!! error TS2339: Property 'name' does not exist on type '{}'.
18+
name;
19+
}
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//// [useUnknownInCatchVariables02.ts]
2+
try {
3+
// ...
4+
}
5+
catch ({ name }) {
6+
name;
7+
}
8+
9+
try {
10+
// ...
11+
}
12+
catch ({ name }: unknown) {
13+
name;
14+
}
15+
16+
17+
//// [useUnknownInCatchVariables02.js]
18+
try {
19+
// ...
20+
}
21+
catch (_a) {
22+
var name = _a.name;
23+
name;
24+
}
25+
try {
26+
// ...
27+
}
28+
catch (_b) {
29+
var name = _b.name;
30+
name;
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
=== tests/cases/compiler/useUnknownInCatchVariables02.ts ===
2+
try {
3+
// ...
4+
}
5+
catch ({ name }) {
6+
>name : Symbol(name, Decl(useUnknownInCatchVariables02.ts, 3, 8))
7+
8+
name;
9+
>name : Symbol(name, Decl(useUnknownInCatchVariables02.ts, 3, 8))
10+
}
11+
12+
try {
13+
// ...
14+
}
15+
catch ({ name }: unknown) {
16+
>name : Symbol(name, Decl(useUnknownInCatchVariables02.ts, 10, 8))
17+
18+
name;
19+
>name : Symbol(name, Decl(useUnknownInCatchVariables02.ts, 10, 8))
20+
}
21+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
=== tests/cases/compiler/useUnknownInCatchVariables02.ts ===
2+
try {
3+
// ...
4+
}
5+
catch ({ name }) {
6+
>name : any
7+
8+
name;
9+
>name : any
10+
}
11+
12+
try {
13+
// ...
14+
}
15+
catch ({ name }: unknown) {
16+
>name : any
17+
18+
name;
19+
>name : any
20+
}
21+

0 commit comments

Comments
 (0)