Reputation: 2382
I have error in my project, and I need to handle this by using try, catch and finally.
I can use this in JavaScript but not in Typescript.
When I put Exception as argument in typescript catch statement, why it is not accepting this?
here is the code.
private handling(argument: string): string {
try {
result= this.markLibrary(argument);
}
catch(e:Exception){
result = e.Message;
}
return result;
}
I need an exception message here but I can't get. And I got the below error.
Catch clause variable cannot have a type annotation.
Upvotes: 190
Views: 452462
Reputation: 1
Using type as unknown should work
Use the below snippet as example
try {
//your code
} catch (e: unknown) {
if (e instanceof Error) {
setErrorMessage(e.message)
}
}
Upvotes: 0
Reputation: 114
You should avoid to use type casting with as
unless you 100% sure what you are expecting because you will overwrite the type of the error and you are not able to test it anymore or to pass it in the verified way.
This would be actually the right answer
import BaseError from './src/errors/BaseError'
const fn = () => {
throw new Error('Any js error')
}
try {
fn()
} catch (err) {
const errMsg = 'Can not create chat completion'
if (err instanceof Error) {
throw new BaseError(errMsg, err)
}
throw new Error(errMsg, { cause: err })
}
throw new BaseError(errMsg, err as Error)
then you would tell your custom error class that err is always an Error but this is risky and can cause problem the more specifc your error handling is or what you expect. E.g. when you expect AxiosError then you reached the catch block maybe with a normal js error instead but because you would write HttpClientError(errMsg, err as AxiosError)
you would pass the normal error instance as AxiosErrorHere is another example for a unit test:
it('should throw an error when initializing connection with mongoose fails', async () => {
try {
await mongooseUtils['init']()
assert.fail('This line should not be reached')
} catch (err) {
if (err instanceof BaseError) {
const typedErr = err
expect(typedErr.error?.message).toBe(expectedErrorMessage)
expect(typedErr.message).toBe(
'[ModelManager] - Error while initializing connection with MongoDB'
)
return
}
assert.fail('This line should not be reached')
}
})
Here is an example for integration test with axios:
import axios, { AxiosError } from 'axios'
import { it, expect, assert } from 'vitest'
import { type IBaseError, StatusCodes } from 'error-manager-helper'
it('should return 500 with BaseError details - error passed', async() => {
try {
await axios.get('https://localhost:3000/base-error?param=wrong')
assert.fail('This line should not be reached')
} catch (err) {
if (err instanceof AxiosError) {
expect(err.status).to.equal(StatusCodes.INTERNAL_SERVER_ERROR)
const data = err.response?.data as IBaseError
expect(data.error).toEqual(`Error: ${errorMessageFromService}`)
expect(data.message).toBe(errorMessage)
return
}
assert.fail('This line should not be reached')
}
})
Upvotes: 0
Reputation: 39
If you're using Axios and can't figure out the type of Error, you can do this:
import axios, { AxiosError } from "axios"
try {
const response = await get('https://url.com/users/')
return response.data
} catch (error) {
throw new Error((error as AxiosError).message)
}
Upvotes: 2
Reputation: 249486
Typescript 4.0 added the ability to specify unknown
and any
on catch variables (Issue) And typescript 4.4 added the ability to make unknown
the default on catch variables (PR) using the useUnknownInCatchVariables
flag.
With this flag the following is now possible:
catch(e){
result = e.message; // error under useUnknownInCatchVariables
if (typeof e === "string") {
e.toUpperCase() // works, `e` narrowed to string
} else if (e instanceof Error) {
e.message // works, `e` narrowed to Error
}
}
Specifying arbitrary types on catch variables is still not supported.
Typescript does not support annotations on the catch variable. There is a proposal to allow this but it is still being discussed (see here).
Your only solution is to use a type assertion or an extra variable:
catch(_e){
let e:Error= _e;
result = e.message;
}
catch(e){
result = (e as Error).message;
}
Unfortunately this will work as well and is completely unchecked:
catch(e){
result = e.MessageUps;
}
Note
As you can read in the discussion on the proposal, in JS not everything that is thrown has to be an Error
instance, so beware of this assumption.
Maybe tslint with no-unsafe-any
would help catch this.
Upvotes: 187
Reputation: 1113
Can try this
try {...}
catch (e) {
console.log((e as Error).message);
}
Also any
type works as well.
try {...}
catch (e:any) {
console.log(e.message);
}
But instanceof
throw error.
try {...}
catch (e) {
console.log((e instanceof Error).message);
}
Upvotes: 28
Reputation: 10897
catch (e) {
const error = e as <Your custom error type>;
...
}
Upvotes: 3
Reputation: 84
What works in my case is like this. To print to terminal:
catch(error){
log('any_text', error as Error);
}
or call metod:
catch(error){
anything_here((error as Error).message),
}
Upvotes: 3
Reputation: 74490
With TypeScript 4.0, you can set unknown
as catch clause variable type:
unknown
is safer thanany
because it reminds us that we need to perform some sorts of type-checks before operating on our values. (docs)
try { /* ... */ }
catch (e: unknown) { // <-- note `e` has explicit `unknown` type
e.message // errors
if (typeof e === "string") {
e.toUpperCase() // works, `e` narrowed to string
} else if (e instanceof Error) {
e.message // works, `e` narrowed to Error
}
// ... handle other error types
}
Update: TypeScript 4.4 provides a config flag --useUnknownInCatchVariables
to let catch-variables default to type unknown
. This is also automatically enabled with the --strict
flag.
Upvotes: 118
Reputation: 3387
Firstly, you need to define the result
variable
let result;
Secondly, you can't define the type of e - as the message said, so in case you want to force the type of e, use
catch(e){
result = (e as Exception).Message;
}
or
catch(e){
result = (<Exception>e).Message;
}
Otherwise, it should still work because e will have the type as any
catch (e) {
result = e.Message;
}
Upvotes: 15