TypeScript error

TS18046: A value of type unknown is used without a check

  • Error TS18046
  • Reported with useUnknownInCatchVariables
  • Reported with strict
  • Tested with TypeScript 5.9

error TS18046: 'err' is of type 'unknown'. is reported when code reads a property of, or calls, a value typed unknown without narrowing it first. The everyday source is catch (err): under strict, useUnknownInCatchVariables types the caught value as unknown, because JavaScript can throw anything, not only Error objects.

The same check on an expression without a name, such as the result of a function whose @returns is unknown, is TS2571 (Object is of type 'unknown'.). Both say the same thing: prove what the value is before using it.

At a glance

CodeTS18046
Message'{0}' is of type 'unknown'.
Also on this page: TS2571 Object is of type 'unknown'.
TypeScript's categoryerror
Listed underNull, undefined and unknown
Turned on by useUnknownInCatchVariables, strict
In .js files Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file

The messages are TypeScript's own text from its diagnostic messages file (Apache-2.0); {0} is filled in by tsc for each error.

What it looks like

config.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: config.js(9,12): error TS2571: Object is of type 'unknown'. config.js(12,47): error TS18046: 'err' is of type 'unknown'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. config.js(9,12): error TS2571: Object is of type 'unknown'. config.js(12,47): error TS18046: 'err' is of type 'unknown'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. config.js(9,12): error TS2571: Object is of type 'unknown'. config.js(12,47): error TS18046: 'err' is of type 'unknown'. checked 21 October 2026
/** @returns {unknown} */
function readSettings() {
  return JSON.parse(localStorage.getItem("settings") ?? "{}");
}

export function loadPort() {
  try {
    return readSettings().port;error TS2571: Object is of type 'unknown'.
  } catch (err) {
    console.error(`Could not read settings: ${err.message}`);error TS18046: 'err' is of type 'unknown'.
    return 3000;
  }
}
The error in a catch clause, and a value typed unknown.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

What causes it

  • useUnknownInCatchVariables is on (part of strict), so catch (err) gives err the type unknown, and the code reads err.message.
  • A function returns unknown (a JSON reader, a message handler), and its result is used directly; that is TS2571 when the result is not stored in a variable.

How to fix it

Narrow the value first

For errors, err instanceof Error ? err.message : String(err) covers both an Error and anything else that was thrown. For data, check the shape with typeof, in and !== null, or write a type guard function once and reuse it.

config.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
/** @returns {unknown} */
function readSettings() {
  return JSON.parse(localStorage.getItem("settings") ?? "{}");
}

export function loadPort() {
  try {
    const settings = readSettings();
    if (typeof settings === "object" && settings !== null && "port" in settings && typeof settings.port === "number") {
      return settings.port;
    }
    return 3000;
  } catch (err) {
    console.error(`Could not read settings: ${err instanceof Error ? err.message : String(err)}`);
    return 3000;
  }
}
Narrow the unknown value before using it.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

Or annotate the catch clause, if you accept the risk

useUnknownInCatchVariables: false restores the older any for catch variables across the project, and catch (/** @type {any} */ err) does it for one clause. Both trade the check for convenience; the instanceof line is short enough to prefer.

Gotchas

  • instanceof Error is false for errors from another realm (an iframe) and for libraries that throw plain objects; the String(err) fallback still prints something.
  • unknown is the type-safe counterpart of any: assigning anything to it is allowed, using it is not. The any and unknown page compares them.

Sources

Last reviewed 20 October 2026.