diff --git a/app/routes/posts/proposal-safe-assignment-operator.mdx b/app/routes/posts/proposal-safe-assignment-operator.mdx new file mode 100644 index 0000000..6c43fd7 --- /dev/null +++ b/app/routes/posts/proposal-safe-assignment-operator.mdx @@ -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が特段好きみたいなタイプでもないですが、こういう取り組みはとても大好きです。 +引き続き応援したいです。 \ No newline at end of file