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

avatar

Borislav Hadzhiev

Last updated: Mar 14, 2022

banner

Photo from Unsplash

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

The error "Catch clause variable type annotation must be 'any' or 'unknown'" occurs when we try to type the error variable in a catch block. To solve the error, remove the typing and use a type guard to check if the error is of a specific type, e.g. if (err instanceof Error){}.

Here is an example of how the error occurs.

index.ts
async function getNumber() { try { const result = await Promise.resolve(42); return result; // ⛔️ Error: Catch clause variable type // annotation must be 'any' or 'unknown' if specified.ts(1196) } catch (err: Error) { console.log(err.message); } }

We cannot guarantee that the error in the catch block will be an Error instance ahead of time, so TypeScript sets its type to unknown to avoid any unexpected runtime errors.

To get around this, we have to use a type guard to narrow down the type of the object before accessing a specific property.

index.ts
async function getNumber() { try { const result = await Promise.resolve(42); return result; } catch (err) { if (err instanceof Error) { // 👉️ err is type Error here console.log(err.message); } console.log('Unexpected error', err); } }

We used the instanceof operator to check if err is an instance of the Error object.

You could use this approach to check if the error variable in the catch block is an instance of any specific Error class, even if you have CustomError classes.

It is only safe to access the message property once we've narrowed down the type in the if block, otherwise the type of the err variable is unknown.

If this approach doesn't work for you and you need to type the error variable in the catch block, you can use a type assertion.

index.ts
async function getNumber() { try { const result = await Promise.resolve(42); return result; } catch (err) { const typedError = err as Error; console.log(typedError?.message); } }

We explicitly typed the err variable in the catch block, even though there is no way to guarantee that all caught errors will be of the specific type.

If you are using the axios package and need to type the error in the catch block as an AxiosError, use the isAxiosError() helper function.

index.ts
import axios from 'axios'; async function getData() { try { // 👉️ ... fetch data here } catch (error) { if (axios.isAxiosError(error)) { console.log('error message: ', error.message); // 👇️ error: AxiosError<any, any> return error.message; } else { console.log('unexpected error: ', error); return 'An unexpected error occurred'; } } }

The isAxiosError function is used as a type guard. In the if block we can access all of the properties an AxiosError has, e.g. config, code, request and response.

Conclusion #

The error "Catch clause variable type annotation must be 'any' or 'unknown'" occurs when we try to type the error variable in a catch block. To solve the error, remove the typing and use a type guard to check if the error is of a specific type, e.g. if (err instanceof Error){}.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.