Skip to content
webtype.orgwebtype.orgTS1196

    ↑↓ move · ⏎ open · esc close

    TS1196

    Typing a catch variable

    Catch clause variable type annotation must be 'any' or 'unknown' if specified.

    The compiler’s own words. Not translated — this is the string you pasted into a search box.

    JavaScript lets anything be thrown, so the compiler cannot promise that what lands in a catch clause is an `Error`. `unknown` is the only honest annotation.

    Reproduction

    try {
      JSON.parse('{')
    } catch (error: Error) {
      throw error
    }

    The build asserts this emits exactly this code.

    Why the compiler says this

    `throw` accepts any value at all — a string, a number, `undefined`, an object that merely resembles an error — and the throw site may be anywhere, including a library you do not control. A normal annotation is a claim the compiler checks at every assignment; this one it could never check, because there is no assignment to look at. So the language allows exactly the two types that make no claim: `unknown`, which forces you to narrow, and `any`, which is there for code written before that was possible.

    Fixes

    1. 01
      try {
        JSON.parse('{')
      } catch (error: unknown) {
        if (error instanceof SyntaxError) throw error
        throw new Error(String(error))
      }

      Annotate `unknown` and narrow with `instanceof`. The check you were skipping is the one that makes the rest of the block safe.

    2. 02
      try {
        JSON.parse('{')
      } catch (error) {
        const reason = error instanceof Error ? error.message : String(error)
        throw new Error(reason)
      }

      Or write no annotation at all. Under `strict` the variable is already `unknown`, so the annotation was never adding anything.

    Takeaway

    You cannot declare what you will catch, only what you will accept. Narrow inside the block, and treat "it is an Error" as something to check rather than to assume.

    Errors