Add flag to change catch variables' default types to unknown (#41013)

* Add test case for 'useUnknownInCatchVariables'.

* Add new 'useUnknownInCatchVariables' flag.

* Accepted baselines.

* Add test for catch variable explicitly typed as 'any'.

* Accepted baselines.

* Move option under 'strict'.

* Accepted baselines.

* 'useUnknownInCatchVariables' is strict in command line help.
This commit is contained in:
Daniel Rosenwasser
2021-06-03 13:12:56 -07:00
committed by GitHub
parent 6baa1bec64
commit 9906092db2
32 changed files with 378 additions and 18 deletions
+2 -1
View File
@@ -346,6 +346,7 @@ namespace ts {
const strictOptionalProperties = getStrictOptionValue(compilerOptions, "strictOptionalProperties");
const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny");
const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis");
const useUnknownInCatchVariables = getStrictOptionValue(compilerOptions, "useUnknownInCatchVariables");
const keyofStringsOnly = !!compilerOptions.keyofStringsOnly;
const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : ObjectFlags.FreshLiteral;
@@ -9012,7 +9013,7 @@ namespace ts {
if (isCatchClauseVariableDeclarationOrBindingElement(declaration)) {
const typeNode = getEffectiveTypeAnnotationNode(declaration);
if (typeNode === undefined) {
return anyType;
return useUnknownInCatchVariables ? unknownType : anyType;
}
const type = getTypeOfNode(typeNode);
// an errorType will make `checkTryStatement` issue an error
+9
View File
@@ -632,6 +632,15 @@ namespace ts {
category: Diagnostics.Type_Checking,
description: Diagnostics.Raise_error_on_this_expressions_with_an_implied_any_type,
},
{
name: "useUnknownInCatchVariables",
type: "boolean",
affectsSemanticDiagnostics: true,
strictFlag: true,
showInSimplifiedHelpView: true,
category: Diagnostics.Type_Checking,
description: Diagnostics.Type_catch_clause_variables_as_unknown_instead_of_any,
},
{
name: "alwaysStrict",
type: "boolean",
+4
View File
@@ -5198,6 +5198,10 @@
"category": "Message",
"code": 6802
},
"Type catch clause variables as 'unknown' instead of 'any'.": {
"category": "Message",
"code": 6803
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
+1
View File
@@ -6048,6 +6048,7 @@ namespace ts {
/* @internal */ suppressOutputPathCheck?: boolean;
target?: ScriptTarget; // TODO: GH#18217 frequently asserted as defined
traceResolution?: boolean;
useUnknownInCatchVariables?: boolean;
resolveJsonModule?: boolean;
types?: string[];
/** Paths used to compute primary types search locations */
+1
View File
@@ -6088,6 +6088,7 @@ namespace ts {
| "strictPropertyInitialization"
| "strictOptionalProperties"
| "alwaysStrict"
| "useUnknownInCatchVariables"
;
export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean {
+1
View File
@@ -2919,6 +2919,7 @@ declare namespace ts {
suppressImplicitAnyIndexErrors?: boolean;
target?: ScriptTarget;
traceResolution?: boolean;
useUnknownInCatchVariables?: boolean;
resolveJsonModule?: boolean;
types?: string[];
/** Paths used to compute primary types search locations */
+1
View File
@@ -2919,6 +2919,7 @@ declare namespace ts {
suppressImplicitAnyIndexErrors?: boolean;
target?: ScriptTarget;
traceResolution?: boolean;
useUnknownInCatchVariables?: boolean;
resolveJsonModule?: boolean;
types?: string[];
/** Paths used to compute primary types search locations */
@@ -120,7 +120,7 @@ class Foo {
>Aborter : typeof Aborter
} catch (error) {
>error : any
>error : unknown
if (this.abortController !== undefined) {
>this.abortController !== undefined : boolean
@@ -0,0 +1,5 @@
{
"compilerOptions": {
"useUnknownInCatchVariables": true
}
}
@@ -19,10 +19,10 @@ function f1() {
>a : number
}
catch (e) {
>e : any
>e : unknown
throw e;
>e : any
>e : unknown
}
finally {
if (a != null && a.toFixed(0) == "123") {
@@ -55,7 +55,7 @@ function f2() {
>1 : 1
}
catch (e) {
>e : any
>e : unknown
x = 2;
>x = 2 : 2
@@ -63,7 +63,7 @@ function f2() {
>2 : 2
throw e;
>e : any
>e : unknown
}
finally {
x; // 0 | 1 | 2
@@ -87,7 +87,7 @@ function f3() {
>1 : 1
}
catch (e) {
>e : any
>e : unknown
x = 2;
>x = 2 : 2
@@ -118,7 +118,7 @@ function f4() {
>1 : 1
}
catch (e) {
>e : any
>e : unknown
x = 2;
>x = 2 : 2
@@ -149,7 +149,7 @@ function f5() {
return;
}
catch (e) {
>e : any
>e : unknown
x = 2;
>x = 2 : 2
@@ -178,7 +178,7 @@ function f6() {
>1 : 1
}
catch (e) {
>e : any
>e : unknown
x = 2;
>x = 2 : 2
@@ -211,7 +211,7 @@ function f7() {
return;
}
catch (e) {
>e : any
>e : unknown
x = 2;
>x = 2 : 2
@@ -324,7 +324,7 @@ function f10() {
return;
}
catch (e) {
>e : any
>e : unknown
x = 2;
>x = 2 : 2
@@ -388,7 +388,7 @@ function f11() {
}
}
catch (e) {
>e : any
>e : unknown
x; // 0 | 1 | 2
>x : 0 | 1 | 2
@@ -466,7 +466,7 @@ function f12() {
}
}
catch (e) {
>e : any
>e : unknown
x; // 0 | 1 | 2
>x : 0 | 1 | 2
@@ -576,7 +576,7 @@ function t1() {
>'x' : "x"
}
catch (e) {
>e : any
>e : unknown
return null;
>null : null
@@ -626,7 +626,7 @@ function notallowed(arg: number) {
finally { }
}
catch (err) {
>err : any
>err : unknown
state.tag;
>state.tag : "one" | "two" | "three"
@@ -770,7 +770,7 @@ function f21() {
>x : 3 | 4 | 5
}
catch (e) {
>e : any
>e : unknown
x; // 0 | 1 | 2 | 3 | 4 | 5
>x : 0 | 1 | 2 | 3 | 4 | 5
@@ -81,6 +81,7 @@
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -81,6 +81,7 @@
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -81,6 +81,7 @@
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
"noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -81,6 +81,7 @@
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -81,6 +81,7 @@
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -81,6 +81,7 @@
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -81,6 +81,7 @@
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -81,6 +81,7 @@
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -81,6 +81,7 @@
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -44,6 +44,7 @@ Options:
--strictPropertyInitialization Enable strict checking of property initialization in classes.
--strictOptionalProperties Enable strict checking of optional properties.
--noImplicitThis Raise error on 'this' expressions with an implied 'any' type.
--useUnknownInCatchVariables Type catch clause variables as 'unknown' instead of 'any'.
--alwaysStrict Parse in strict mode and emit "use strict" for each source file.
--noUnusedLocals Report errors on unused locals.
--noUnusedParameters Report errors on unused parameters.
@@ -102,6 +102,7 @@ interface Array<T> { length: number; [n: number]: T; }
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -102,6 +102,7 @@ interface Array<T> { length: number; [n: number]: T; }
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -102,6 +102,7 @@ interface Array<T> { length: number; [n: number]: T; }
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -102,6 +102,7 @@ interface Array<T> { length: number; [n: number]: T; }
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -102,6 +102,7 @@ interface Array<T> { length: number; [n: number]: T; }
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -102,6 +102,7 @@ interface Array<T> { length: number; [n: number]: T; }
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "strictOptionalProperties": true, /* Enable strict checking of optional properties. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
@@ -68,7 +68,7 @@ throw new Error('Unreachable')
try {
}
catch (e) {
>e : any
>e : unknown
}
/**
@@ -0,0 +1,47 @@
tests/cases/compiler/useUnknownInCatchVariables01.ts(6,12): error TS2339: Property 'toUpperCase' does not exist on type 'unknown'.
tests/cases/compiler/useUnknownInCatchVariables01.ts(7,10): error TS2356: An arithmetic operand must be of type 'any', 'number', 'bigint' or an enum type.
tests/cases/compiler/useUnknownInCatchVariables01.ts(8,10): error TS2349: This expression is not callable.
Type '{}' has no call signatures.
==== tests/cases/compiler/useUnknownInCatchVariables01.ts (3 errors) ====
try {
// ...
}
catch (e) {
// error!
void e.toUpperCase();
~~~~~~~~~~~
!!! error TS2339: Property 'toUpperCase' does not exist on type 'unknown'.
void e++;
~
!!! error TS2356: An arithmetic operand must be of type 'any', 'number', 'bigint' or an enum type.
void e();
~
!!! error TS2349: This expression is not callable.
!!! error TS2349: Type '{}' has no call signatures.
if (typeof e === "string") {
// works!
// We've narrowed 'e' down to the type 'string'.
console.log(e.toUpperCase());
}
if (e instanceof Error) {
e.stack?.toUpperCase();
}
if (typeof e === "number") {
e.toExponential();
e++;
}
}
try {
// ...
}
catch (e: any) {
// All are allowed.
void e.toUpperCase();
void e.toExponential();
void e();
}
@@ -0,0 +1,67 @@
//// [useUnknownInCatchVariables01.ts]
try {
// ...
}
catch (e) {
// error!
void e.toUpperCase();
void e++;
void e();
if (typeof e === "string") {
// works!
// We've narrowed 'e' down to the type 'string'.
console.log(e.toUpperCase());
}
if (e instanceof Error) {
e.stack?.toUpperCase();
}
if (typeof e === "number") {
e.toExponential();
e++;
}
}
try {
// ...
}
catch (e: any) {
// All are allowed.
void e.toUpperCase();
void e.toExponential();
void e();
}
//// [useUnknownInCatchVariables01.js]
var _a;
try {
// ...
}
catch (e) {
// error!
void e.toUpperCase();
void e++;
void e();
if (typeof e === "string") {
// works!
// We've narrowed 'e' down to the type 'string'.
console.log(e.toUpperCase());
}
if (e instanceof Error) {
(_a = e.stack) === null || _a === void 0 ? void 0 : _a.toUpperCase();
}
if (typeof e === "number") {
e.toExponential();
e++;
}
}
try {
// ...
}
catch (e) {
// All are allowed.
void e.toUpperCase();
void e.toExponential();
void e();
}
@@ -0,0 +1,71 @@
=== tests/cases/compiler/useUnknownInCatchVariables01.ts ===
try {
// ...
}
catch (e) {
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 3, 7))
// error!
void e.toUpperCase();
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 3, 7))
void e++;
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 3, 7))
void e();
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 3, 7))
if (typeof e === "string") {
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 3, 7))
// works!
// We've narrowed 'e' down to the type 'string'.
console.log(e.toUpperCase());
>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.toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --))
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 3, 7))
>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --))
}
if (e instanceof Error) {
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 3, 7))
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
e.stack?.toUpperCase();
>e.stack?.toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --))
>e.stack : Symbol(Error.stack, Decl(lib.es5.d.ts, --, --))
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 3, 7))
>stack : Symbol(Error.stack, Decl(lib.es5.d.ts, --, --))
>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --))
}
if (typeof e === "number") {
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 3, 7))
e.toExponential();
>e.toExponential : Symbol(Number.toExponential, Decl(lib.es5.d.ts, --, --))
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 3, 7))
>toExponential : Symbol(Number.toExponential, Decl(lib.es5.d.ts, --, --))
e++;
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 3, 7))
}
}
try {
// ...
}
catch (e: any) {
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 27, 7))
// All are allowed.
void e.toUpperCase();
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 27, 7))
void e.toExponential();
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 27, 7))
void e();
>e : Symbol(e, Decl(useUnknownInCatchVariables01.ts, 27, 7))
}
@@ -0,0 +1,101 @@
=== tests/cases/compiler/useUnknownInCatchVariables01.ts ===
try {
// ...
}
catch (e) {
>e : unknown
// error!
void e.toUpperCase();
>void e.toUpperCase() : undefined
>e.toUpperCase() : any
>e.toUpperCase : any
>e : unknown
>toUpperCase : any
void e++;
>void e++ : undefined
>e++ : number
>e : unknown
void e();
>void e() : undefined
>e() : any
>e : unknown
if (typeof e === "string") {
>typeof e === "string" : boolean
>typeof e : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>e : unknown
>"string" : "string"
// works!
// We've narrowed 'e' down to the type 'string'.
console.log(e.toUpperCase());
>console.log(e.toUpperCase()) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>e.toUpperCase() : string
>e.toUpperCase : () => string
>e : string
>toUpperCase : () => string
}
if (e instanceof Error) {
>e instanceof Error : boolean
>e : unknown
>Error : ErrorConstructor
e.stack?.toUpperCase();
>e.stack?.toUpperCase() : string
>e.stack?.toUpperCase : () => string
>e.stack : string
>e : Error
>stack : string
>toUpperCase : () => string
}
if (typeof e === "number") {
>typeof e === "number" : boolean
>typeof e : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>e : unknown
>"number" : "number"
e.toExponential();
>e.toExponential() : string
>e.toExponential : (fractionDigits?: number) => string
>e : number
>toExponential : (fractionDigits?: number) => string
e++;
>e++ : number
>e : number
}
}
try {
// ...
}
catch (e: any) {
>e : any
// All are allowed.
void e.toUpperCase();
>void e.toUpperCase() : undefined
>e.toUpperCase() : any
>e.toUpperCase : any
>e : any
>toUpperCase : any
void e.toExponential();
>void e.toExponential() : undefined
>e.toExponential() : any
>e.toExponential : any
>e : any
>toExponential : any
void e();
>void e() : undefined
>e() : any
>e : any
}
@@ -0,0 +1,35 @@
// @useUnknownInCatchVariables: true
try {
// ...
}
catch (e) {
// error!
void e.toUpperCase();
void e++;
void e();
if (typeof e === "string") {
// works!
// We've narrowed 'e' down to the type 'string'.
console.log(e.toUpperCase());
}
if (e instanceof Error) {
e.stack?.toUpperCase();
}
if (typeof e === "number") {
e.toExponential();
e++;
}
}
try {
// ...
}
catch (e: any) {
// All are allowed.
void e.toUpperCase();
void e.toExponential();
void e();
}