JavaScript can throw any value, not only Error objects, so the variable in catch (err) can be anything. With useUnknownInCatchVariables it is typed unknown, and using err.message without a check is an error (TS18046). Without it, err is any and nothing is checked.
It joined strict with TypeScript 4.4, so code that passed under strict before 4.4 can report errors after an upgrade.
At a glance
| Write | Leave it to strict; write "useUnknownInCatchVariables": false only to turn this one check back off |
|---|---|
| On the command line | --useUnknownInCatchVariables |
| Type | boolean |
| Default in TypeScript 5.9 | false (on when strict is on) |
| Default from TypeScript 6.0 | true, through strict (TypeScript 6.0) |
| TypeScript's description | Default catch clause variables as 'unknown' instead of 'any'. |
The description is quoted from TypeScript's own option list (Apache-2.0); see the notices.
Examples
main.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026:
main.js(5,15): error TS18046: 'err' is of type 'unknown'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3.
main.js(5,15): error TS18046: 'err' is of type 'unknown'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3.
main.js(5,15): error TS18046: 'err' is of type 'unknown'. checked 21 October 2026
try {
JSON.parse("{");
} catch (err) {
console.log(err.message);error TS18046: 'err' is of type 'unknown'.
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": [
"*.js"
]
} main.js TypeScript 5.9.3 TypeScript 5.9.3, run 21 October 2026:
No errors. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3.
No errors. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3.
No errors. checked 21 October 2026
try {
JSON.parse("{");
} catch (err) {
console.log(err.message);
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": [],
"useUnknownInCatchVariables": false
},
"include": [
"*.js"
]
} Checking what was thrown
Narrow before you use it: err instanceof Error ? err.message : String(err). That handles throw "oops" and other non-errors too, which is the point of the check.
Gotchas
- Promise rejections in
.catch((err) => …)callbacks are typedanyregardless of this option; the option coverscatchclauses only.
Sources
- TSConfig Reference: useUnknownInCatchVariables · TypeScript
- TypeScript 4.4 release notes · TypeScript handbook
Last reviewed 20 October 2026.