diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2665d50aba123..38c193758be7a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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 diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 7ef4ec55924fe..ecd9e43c7f749 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -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", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 3bbb2affe6730..d2ddbc8b0a4ec 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -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", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f2765d04ebca2..e375b0a77acac 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -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 */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 1970b9db104aa..71689f76c7013 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -6088,6 +6088,7 @@ namespace ts { | "strictPropertyInitialization" | "strictOptionalProperties" | "alwaysStrict" + | "useUnknownInCatchVariables" ; export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index d6ba9868cd499..376ebc377765f 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -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 */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 9f58cc3bbab09..ea5e5d3eeefd4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -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 */ diff --git a/tests/baselines/reference/controlFlowForCatchAndFinally.types b/tests/baselines/reference/controlFlowForCatchAndFinally.types index a041cac8ce09a..c159655a0a816 100644 --- a/tests/baselines/reference/controlFlowForCatchAndFinally.types +++ b/tests/baselines/reference/controlFlowForCatchAndFinally.types @@ -120,7 +120,7 @@ class Foo { >Aborter : typeof Aborter } catch (error) { ->error : any +>error : unknown if (this.abortController !== undefined) { >this.abortController !== undefined : boolean diff --git a/tests/baselines/reference/showConfig/Shows tsconfig for single option/useUnknownInCatchVariables/tsconfig.json b/tests/baselines/reference/showConfig/Shows tsconfig for single option/useUnknownInCatchVariables/tsconfig.json new file mode 100644 index 0000000000000..19c7c22b6926d --- /dev/null +++ b/tests/baselines/reference/showConfig/Shows tsconfig for single option/useUnknownInCatchVariables/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "useUnknownInCatchVariables": true + } +} diff --git a/tests/baselines/reference/tryCatchFinallyControlFlow.types b/tests/baselines/reference/tryCatchFinallyControlFlow.types index 1674907b3a266..b5fb0cf95cc8c 100644 --- a/tests/baselines/reference/tryCatchFinallyControlFlow.types +++ b/tests/baselines/reference/tryCatchFinallyControlFlow.types @@ -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 diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index f26c204d28d9d..6c8947c8c54ef 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -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. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json index 07a154df5b979..2a97b4825f72a 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json @@ -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. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index 29328ff662571..784955168214f 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -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. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index 9455ab8fead3a..2b4bc05d635e2 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -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. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json index 564f925485ad3..ead54b73278ae 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json @@ -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. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index 004a1d1bddc58..8e8363326d7f7 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -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. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index f26c204d28d9d..6c8947c8c54ef 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -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. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index e1fea4afc378a..c9f0dec383b14 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -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. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json index 70c0c8e7491b9..112a8d7067aa9 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -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. */ diff --git a/tests/baselines/reference/tsc/runWithoutArgs/initial-build/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped.js b/tests/baselines/reference/tsc/runWithoutArgs/initial-build/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped.js index db5d005ad3d51..409bb21a72b99 100644 --- a/tests/baselines/reference/tsc/runWithoutArgs/initial-build/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped.js +++ b/tests/baselines/reference/tsc/runWithoutArgs/initial-build/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped.js @@ -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. diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js index c0dbd44255950..469659de728ee 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js @@ -102,6 +102,7 @@ interface Array { 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. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js index e6854b8954bf1..bc09ff4894de6 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js @@ -102,6 +102,7 @@ interface Array { 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. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js index 2b51059cee8d1..7a5684c889a0f 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js @@ -102,6 +102,7 @@ interface Array { 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. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js index 65430151ff6a5..e8a6ec3b5093f 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js @@ -102,6 +102,7 @@ interface Array { 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. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js index 430697564a008..601d1b230cada 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js @@ -102,6 +102,7 @@ interface Array { 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. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js index 375bc7f8a5615..883622912912d 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js @@ -102,6 +102,7 @@ interface Array { 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. */ diff --git a/tests/baselines/reference/typedefOnStatements.types b/tests/baselines/reference/typedefOnStatements.types index 007a6a41d7658..c30a83a8afa81 100644 --- a/tests/baselines/reference/typedefOnStatements.types +++ b/tests/baselines/reference/typedefOnStatements.types @@ -68,7 +68,7 @@ throw new Error('Unreachable') try { } catch (e) { ->e : any +>e : unknown } /** diff --git a/tests/baselines/reference/useUnknownInCatchVariables01.errors.txt b/tests/baselines/reference/useUnknownInCatchVariables01.errors.txt new file mode 100644 index 0000000000000..017c3ada88cd0 --- /dev/null +++ b/tests/baselines/reference/useUnknownInCatchVariables01.errors.txt @@ -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(); + } \ No newline at end of file diff --git a/tests/baselines/reference/useUnknownInCatchVariables01.js b/tests/baselines/reference/useUnknownInCatchVariables01.js new file mode 100644 index 0000000000000..1e3a867d11855 --- /dev/null +++ b/tests/baselines/reference/useUnknownInCatchVariables01.js @@ -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(); +} diff --git a/tests/baselines/reference/useUnknownInCatchVariables01.symbols b/tests/baselines/reference/useUnknownInCatchVariables01.symbols new file mode 100644 index 0000000000000..f2261f8c36fbf --- /dev/null +++ b/tests/baselines/reference/useUnknownInCatchVariables01.symbols @@ -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)) +} diff --git a/tests/baselines/reference/useUnknownInCatchVariables01.types b/tests/baselines/reference/useUnknownInCatchVariables01.types new file mode 100644 index 0000000000000..71a25687af0c2 --- /dev/null +++ b/tests/baselines/reference/useUnknownInCatchVariables01.types @@ -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 +} diff --git a/tests/cases/compiler/useUnknownInCatchVariables01.ts b/tests/cases/compiler/useUnknownInCatchVariables01.ts new file mode 100644 index 0000000000000..ca9bdda4acbd0 --- /dev/null +++ b/tests/cases/compiler/useUnknownInCatchVariables01.ts @@ -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(); +} \ No newline at end of file