Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal-safe-assignment-operatorでJSに新しいエラーハンドリングが入るかもしれない #59

Merged
merged 7 commits into from
Dec 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions app/routes/posts/proposal-safe-assignment-operator.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
title: "proposal-safe-assignment-operatorでJSに新しいエラーハンドリングが入るかもしれない"
description: "proposal-safe-assignment-operatorというプロポーザルがあります(多分まだ提出されていないのでstage0ですらない)。JavaScriptにおけるエラーハンドリングといえば、try&catch / then&catchがあると思います。本プロポーザルのそれらの課題に対しての解決方法が面白かったので紹介します。"
date: "2024/12/05"
updatedAt: "2024/12/05"
path: "proposal-safe-assignment-operator"
published: true
---

[2024年 ユウトの一人アドベントカレンダー](https://adventar.org/calendars/9980)の5日目の記事です。

## Intro

[proposal-safe-assignment-operator](https://github.com/arthurfiorette/proposal-safe-assignment-operator)というプロポーザルがあります(多分まだ提出されていないのでstage0ですらない)。
JavaScriptにおけるエラーハンドリングといえば、try&catch / then&catchがあると思います。
本プロポーザルのそれらの課題に対しての解決方法が面白かったので紹介します。

## try&catchの課題

例えば、以下のようなコードがあったします(プロポーザル内のコードを拝借)

```ts
async function getData() {
const response = await fetch("https://api.example.com/data")
const json = await response.json()
return validationSchema.parse(json)
}
```

このコードだとエラーがキャッチされていないので、アプリケーションがクラッシュする可能性があります。

## The Safe Assignment Operator (?=)

キャッチし忘れによるクラッシュを防ぐため、以下のような新しい構文が提案されています。

```ts
async function getData() {
const [requestError, response] ?= await fetch(
"https://api.example.com/data"
)

if (requestError) {
handleRequestError(requestError)
return
}

const [parseError, json] ?= await response.json()

if (parseError) {
handleParseError(parseError)
return
}

const [validationError, data] ?= validationSchema.parse(json)

if (validationError) {
handleValidationError(validationError)
return
}

return data
}
```

`?=`という演算子を新しく追加し、エラーとレスポンスを配列として返しています。
そしてerrorでエラー処理の記述が簡潔になり、キャッチ漏れを減らすことでアプリケーションのクラッシュリスクを低減できます。

本ブログの公開前に少し気になったんですが、errorの時に早期returnするようにしないとdataはnullableになるのか。みたいなのは議論が盛り上がってそうでした。([https://github.com/arthurfiorette/proposal-safe-assignment-operator/issues/30](https://github.com/arthurfiorette/proposal-safe-assignment-operator/issues/30)

そしてこの構文は、コンパイラによって次のような形に変換されます。

```ts
const [error, data] ?= expression
// ↕︎
if (error) {
// catch code
} else {
// try code
}
```

エラーだった場合の条件にしているだけのようです。

## try-expression

先ほど紹介した`?=`だと、他の`??`と似すぎているのもあり、直感的ではないなと、筆者はこれを見た時に思っていました。
実際、似たようなコメントが挙げられていました。([#issues/4#issuecomment-2292234700](https://github.com/arthurfiorette/proposal-safe-assignment-operator/)

なのでアンケートとして幾つかのパターンが提案されていましたが、以下のような書き方が人気みたいです。

```ts
const [error, data] = try mightFail();
const [error, data] = try await mightFail();
```

筆者としても、これだと直感的で良さそうだなと思いました。

## 筆者の感想

正直筆者としては、ここまで発展したJavaScriptに新しいエラーハンドリング方式を入れることって現実的なのかなと、少し考えたりします。
then/catchのメソッドチェーン方式が辛いから(確か)、手続き的にかけるasync/awaitが生まれ、そしてそれのエラーハンドリングとしてtry&catchが入ったはずで、catch漏れのクラッシュなんて今だとlintで防げるのでは、みたいなことも正直思ってしまいます。

というのが感想の一つですが、別に批判したいわけではないです。
別の言語から影響を受けて、それを入れようとしてみる。そしてフィードバックを受け、入れなかった理由がはっきりしていれば、今後のためになるはずです。

筆者は別にJavaScriptが特段好きみたいなタイプでもないですが、こういう取り組みはとても大好きです。
引き続き応援したいです。
Loading