[TypeScript] 將TypeScript 導入到React專案的常見問題- try/catch 的error

施慶銓
6 min readApr 25, 2023

--

先前的文章
- [TypeScript] 將TypeScript 導入到React專案 — 起手式
- [TypeScript] 將TypeScript 導入到React專案的常見問題- createRoot參數錯誤
- [TypeScript] 將TypeScript 導入到React專案的常見問題- Props的型別與預設值
- [TypeScript] 將TypeScript 導入到React專案的常見問題- 基本元件的Prop
- [TypeScript] 將TypeScript 導入到React專案的常見問題- 第三方套件的型別

如何處理try…catch 的error

在加入TypeScript 之前, 我們一般在function 裡面如果有加入try…catch 來捕捉function 發生的錯誤, 通常會是以下的樣子

function getUser() {
try{
// some codes
} catch(error) {
handleError(error)
}
}

catch 會收到ㄧ個error 的參數, 這個error 有可能是Error object, 也有可能單純是字串, 依照這個發送error 給這個function 的來源

當error 是字串

當error 是Error object

或甚至是null 也可以

以此類推也可以是數字, 物件, 布林值, Promise

可到MDN-throw試玩看看

所以, 當加入TypeScript, 這裡error 的型別就要特別處理

在尚未處理的情況下, 會出現以下錯誤訊息

在這個例子當中, setErrorMessage 是接收useState用來更新state的handler

const [errorMessage, setErrorMessage] = useState("");

setErrorMessage只能接收字串參數, 而錯誤訊息給的提示是unknown類型的參數試圖傳入setErrorMessage , 所以導致錯誤

由此可知, 在TypeScript 內 catch block 所收到的error 會是unknown類型

該如何處理?

在面對這個問題的時候, 我有看到一篇處理catch error 型別還不錯的文章: Get a catch block error message with TypeScript

在處理catch error 時, 可以先判斷error 是否為Error Object. 否則一率將error 強制轉型為字串 型別

catch (error) {
if(error instanceof Error) {
setErrorMessage(error.message)
} else {
setErrorMessage(String(error))
}
}

通常專案不會只會遇到一次需要try…catch…的狀況, 所以這時候將這個處理邏輯抽出來成為一個獨立的function比較好

// utilities.js
function handlerError(error: unknown): string{
if(error instanceof Error) {
return error.message
}

return String(error)
}

// MyComponent.tsx
catch (error) {
setErrorMessage(handlerError(error))
}

不過這篇文章的作者提到其他更好的做法

catch error 有可能不是真正的Error object, 所以上面的做法可以做得更嚴謹

// utilities.js
function isErrorWithMessage(error: unknown): error is ErrorWithMessage {
return (
typeof error === 'object' &&
error !== null &&
'message' in error &&
typeof (error as Record<string, unknown>).message === 'string'
)
}

function handlerError(maybeError: unknown): ErrorWithMessage {
if (isErrorWithMessage(maybeError)) return maybeError

try {
return new Error(JSON.stringify(maybeError))
} catch {
// fallback in case there's an error stringifying the maybeError
// like with circular references for example.
return new Error(String(maybeError))
}
}

function getErrorMessage(error: unknown):string {
return handlerError(error).message
}

// MyComponent.tsx
catch (error) {
setErrorMessage(getErrorMessage(error))
}

用這樣的方式確保 getErrorMessage 可以接收任何型別的error, 並且絕對會回傳字串 型別的訊息.

References

--

--

施慶銓
施慶銓

No responses yet