2023-08-22 TypeScript error handling


对于 error handling,我的风格碰巧和 Ruby 作者 Matz 一致,虽然是巧合,但是增加了我的信心。

先说 error handling 需要解决哪些问题?

  1. 不能放任 error 使其导致程序崩溃
  2. 不能让 error handling 多到影响原本的功能

我常用的编程语言有 TypeScript 和 Elixir,Elixir 不用说了,我很喜欢它的 error handling 机制。

我主要分享一下我自己使用 TypeScript 时的 error handling 风格。

1. 80% 的情况下,我会直接使用 try-catch 处理 Exception,不用其他奇技淫巧

2. 我会尽量避免 Nested try blocks,形如:

try {
  try {
    throw new Error("oops");
  } finally {
    console.log("finally");
  }
} catch (ex) {
  console.error("outer", ex.message);
}

为了避免嵌套 try blocks,我会参考 Elixir/golang/Swift 的方式返回一个数组包含 [isError, data/error]

形如:

//
function doSomething() {
  try {
    return [false, data]
  } catch(error) {
    return [true, error]
  }
}

const [isError, data] = doSomething()
if(isError) {
  // data is error
  // your fallback
}
// data is expected data
// next ...

supabase-js 和 zod 也采用了类似的风格,只是细节不太一样,这也增强了我的信心。

// supabase-js
const { data, error } = await supabase
  .from('countries')
  .select()
// zod .safeParse
stringSchema.safeParse(12);
// => { success: false; error: ZodError }

stringSchema.safeParse("billie");
// => { success: true; data: 'billie' }

为什么我用 Array 而不是 Object 作为返回值?因为我觉得 ES6 以后数组取值也很简单。

3. 我不会强迫症似的穷举所有的 Exception 类型

// good
async function doSomething(): Promise<Data>

// bad
async function doSomething(): Promise<Data
      | RpcException
      | ChargeFeeHasNotBeenPaidException
      | BadRequestException
      | UnusableFacilityException
      | NotBusinessDayException>

当然,npm package, public library 除外。

4. 我不会让 Exception 不能导致整个 App 崩溃

MVC 风格的 web server app 的 exception 最好控制在 controller 层,不要因为个别的 API 异常导致整个 App 崩溃或者重启。

类似 Remix.run 这样的框架甚至可以将 exception 控制在 UI component 级别,不过我不过分强求,只要别让整个 App 崩溃就行。

5. 我会适当记录 Exception log

6. error handling 我不采用 TDD

如果要在动手开发功能前就想明白有多少种 errors 需要处理,对我来说有点难,或许尼古拉 特斯拉那样的大脑可以吧。

实际 coding 时,我的 workflow

  1. smoking mode 冒烟模式:忽略 error 先把正常流程完成,可运行。
  2. big try-catch: 用一个 try-catch 包裹全部代码,防止 App 崩溃。
  3. error handlings: 具体分析一下该使用 try-catch 还是 Result type。

refs

这是我的个人风格,不奢求成为主流,只希望将来有机会合作的朋友能事先了解我的个人风格。