---
title: neverthrow is not for meを 再考する
tags: 
author: [Rinrin](https://www.docswell.com/user/rin2yh)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/P7XQ831DEX.jpg?width=480
description: TSKaigi2026〜アフターパーティー〜 のスライドです。 neverthrowを一度見送ってからなぜ採用に至ったのか、その過程と判断を記しました。 https://every.connpass.com/event/393937/
published: June 12, 26
canonical: https://www.docswell.com/s/rin2yh/Z4N4NW-rethinking-neverthrow-is-not-for-me
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/P7XQ831DEX.jpg)

neverthrow is not for meを
再考する
TSKaigi2026〜アフターパーティー〜
株式会社スリーシェイク Rinrin
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 2

![Page Image](https://bcdn.docswell.com/page/37K9KY2D7D.jpg)

自己紹介
●
●
●
●
Copyright © 3-shake, Inc. All Rights Reserved.
名前：Rinrin / 林 侑生
所属：株式会社スリーシェイク Sreake事業部
業務：決済基盤のリプレース
今回再考したきっかけ
○ 「neverthrowはnot for me」関連投稿が
散見
○ 昨年開発時に導入を見送り、同感だった
○ 一方で、ふと今も同感なのか疑念が生じた
2


# Page. 3

![Page Image](https://bcdn.docswell.com/page/LJ3WZ94PJ5.jpg)

会社紹介
会社名
株式会社スリーシェイク
設立日
2015/1/15
代表者
代表取締役社長
所在地
東京都中央区銀座8丁目21番1号
住友不動産汐留浜離宮ビル7F
吉田 拓真
Googleクラウド・AWSの両方のエンジニアリングに強みを持つ
Mission: インフラをシンプルにして
イノベーションが起こりやすい世界を作る
Vision: 労苦〈Toil〉を無くすサービスを適正な価格で提供し続ける
従業員: 200名over
100
日本のSREをリードする
あらゆるサービスを
連携するハブになる
インフラ・アプリ・データ・セキュリティ・AI
全方位で顧客の内製化を推進する伴走支援
あらゆるSaaSをノーコードで連携する
クラウド型ETL/データパイプラインSaaS
Engineer
50
0
事業者が抱える
セキュリティリスクをゼロに
「いいエンジニア」を
あなたのチームに
セキュリティ対策をワンストップで
実現する脆弱性診断SaaS
ハイスキル人材の紹介とHR戦略支援の両輪で
エンジニア組織の課題に併走
60%
2015
2016 2017 2018 2019 2020 2021 2022
会社・事業部説明資料（SpeakerDeck）
3


# Page. 4

![Page Image](https://bcdn.docswell.com/page/8JDKRGQ3EG.jpg)

Sreakeの事業
SREの思想・技術をベースに、4つの領域でプロフェッショナルサービスを提供しています
・アプリケーションモダナイゼーション
・プラットフォーム構築 / 運用高度化
API / マイクロサービス / リファクタリング
Google Cloud / AWS / Kubernetes / IaC
・信頼性 / 生産性 / DevEx向上
・開発プロセス改善・高度化
SRE / o11y / CI/CD / Platform Engineering
SRE / DevOps
AI駆動開発 / 開発環境 / CI/CD
・セキュリティ強化
アセスメント / SIEM / WAF / CSIRT
4
Application
Modernization
・組織組成・強化
アジャイル / スクラム / チームトポロジー
・生成AI導入 / 活用
ワークショップ / RAG
・データベース構築 / 移行 / 性能改善
・AIエージェント開発
PostgreSQL / MySQL / Spanner / TiDB
MCP / A2A / 既存システム連携
AI / ML
・モデル開発環境構築
MLOps / データフライホイール
・データ基盤構築
Looker / Snowﬂake / BigQuery / Redshift
DBRE
※記載されている会社名、製品名、サービス名等は、各社の登録商標または商標です
Copyright © 3-shake, Inc. All Rights Reserved.
3


# Page. 5

![Page Image](https://bcdn.docswell.com/page/VEPKW3LP78.jpg)

目次
1.
2.
3.
4.
前提
Why neverthrow is not for me?
neverthrow is not for meを再考する
まとめ
5


# Page. 6

![Page Image](https://bcdn.docswell.com/page/27VV84QV7Q.jpg)

01
前提
Copyright © 3-shake, Inc. All Rights Reserved.
6


# Page. 7

![Page Image](https://bcdn.docswell.com/page/5JGL51W17L.jpg)

try...catch文の現状
型安全性の欠如
TypeScript側は対応しない
上位モジュールから「throwされた際に何が飛ぶ
か」が型に出ない
TypeScript側で今後対応の予定はない
●
何でもthrowできる仕様（MDN）
●
カスタムエラー / 汎用Error / プリミティブ /
値
●
●
Javaでは型でthrowを表現可能
Javaのthrows句を参考に導入する提案
○
→Not Planned（予定なし）
○
microsoft/TypeScript #13219
解決策は言語側ではなく、ライブラリや言語の利用者に委ねられる形に...
Copyright © 3-shake, Inc. All Rights Reserved.
7


# Page. 8

![Page Image](https://bcdn.docswell.com/page/47QYZD3NEP.jpg)

neverthrowとは
コンセプト
主な特徴
&quot;How do we encode failability into the typesystem?&quot;
— neverthrow 開発者ブログより
訳：どのようにしてfailability:失敗可能性を型システムに組み込むか？
●
throw を使わず、エラーを値として返す
●
Result型（Ok/Err）への明示的な変換
●
エラー処理漏れを防ぐLintルールまでセット
// プログラム例
const ok = &lt;T, E&gt;(value: T): Result&lt;T, E&gt; =&gt; new Ok(value)
const err = &lt;T, E&gt;(error: E): Result&lt;T, E&gt; =&gt; new Err(error)
const makeHttpRequest = async (url: string): Promise&lt;Result&lt;ResponseData, Error&gt;&gt; =&gt; {
if (!isUrl(url)) return err(new Error(&#039;Invalid URL&#039;))
// other business logic here...
return ok({ ... })
}
関数型プログラミング由来のResult型で解決するライブラリ
8
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 9

![Page Image](https://bcdn.docswell.com/page/KE4W3Z13J1.jpg)

02
Why neverthrow is not for me?
Copyright © 3-shake, Inc. All Rights Reserved.
9


# Page. 10

![Page Image](https://bcdn.docswell.com/page/L71Y1RGZJG.jpg)

neverthrow導入のきっかけ
01. TSKaigi 2025での認知
昨年のセッションで紹介され、Result型を用いたエラーハンド
リングを知るきっかけに。
02. 堅牢な実装パターンの提示
例外を投げない「堅牢な設計」の具体例として紹介されてお
り、強い関心を持つ。
03. 直感的なパターンマッチ
正常系と異常系を型システムで網羅的に扱えるわかりやすさ
に惹かれた。
TSKaigi2025のセッション：fast-checkとneverthrowのPBT+Result型
で堅牢なビジネスロジックを実現する
10
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 11

![Page Image](https://bcdn.docswell.com/page/G7WG81K6E2.jpg)

導入して見えた課題
02. 可読性
01. チーム内の認知コスト
●
●
TSらしくない記法と概念への戸惑い
●
パターンマッチの慣習がなく認知コストが
高い
●
andTee等のメソッドチェーンは直感的な
連想が難しい
fromPromise の冗長さ
try...catchに近く、可読性に変化なし
import { ResultAsync } from &#039;neverthrow&#039;
import { insertIntoDb } from &#039;imaginary-database&#039;
// insertIntoDb(user: User): Promise&lt;User&gt;
const res = ResultAsync.fromPromise(
insertIntoDb(myUser),
() =&gt; new Error(&#039;Database error&#039;)
)
// `res` has a type of ResultAsync&lt;User, Error&gt;
Copyright © 3-shake, Inc. All Rights Reserved.12


# Page. 12

![Page Image](https://bcdn.docswell.com/page/4JZL8PZRE3.jpg)

自前実装してみた
declare const TAG: unique symbol;
// シンボルで成功 /失敗を厳密に区別した Result型
type Success&lt;T&gt; = { data: T; readonly [TAG]: &quot;success&quot; };
type Failure&lt;E extends Error&gt; = { error: E; readonly [TAG]: &quot;failure&quot; };
export type Result&lt;T, E extends Error&gt; = Success&lt;T&gt; | Failure&lt;E&gt;;
// 必要最低限の APIだけ：判定関数 と async→Result 変換ラッパー
isFailure(result) / wrapAsyncCall(fn, cleanup?)
特徴
●
関数は最低限（判定 + async変換）に絞る
●
●
利用側は if (isFailure(result)) で早期return
Goに近い書き心地でWeb開発フレンドリー
デメリット
● neverthrowの堅牢性を失う
●
自前実装のため、保守コストが発生
 Symbol - JavaScript | MDN
12
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 13

![Page Image](https://bcdn.docswell.com/page/YE6WPMZ1EV.jpg)

03
neverthrow is not for meを再考する
Copyright © 3-shake, Inc. All Rights Reserved.
13


# Page. 14

![Page Image](https://bcdn.docswell.com/page/GE5MKZWLE4.jpg)

保守の目線で再考する
ライブラリ(neverthrow)
●
著名なライブラリの一つである
○
●
安易な設計判断だったかもしれない
●
求める体験に相当するAPIがあるかもしれない
今後継続的にメンテナンスされる
●
一部APIを使わないという選択肢もあったはず
Maintenance status #670
●
生成AI時代でも「全て実装する」は正解ではな
い
○
●
GitHubのスター数 7.5K
自前実装
流行りのサプライチェーンリスク問題？
○
○
npmの設定やpnpm等パッケージマネージャ
側で対応可能
自前で実装する理由にはならない
○
コア要件をどのくらい満たすか、が重要
参考：「OSSがあるなら自作するな」は AI時代も正しいか
── Build vs Adopt の新しい判断基準
14
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 15

![Page Image](https://bcdn.docswell.com/page/9729WRQ3JR.jpg)

neverthrowをもう一度見てみる
1. コア要件の充足
2. 採用のグラデーション
自作で得たかった性質をほとんど満たしてい
た
独自メソッドやfromPromiseは選択次第
●
●
●
エラーを値として扱う
○ try...catch文の課題を解決する
型でデータとエラーを厳密に区別する
早期リターン可能
○ result.isErr()
○ Goのようにハンドリング可能
●
●
全てのAPIを無理に使う必要はない
○ メソッドチェーンをほとんど使わない
など
冗長なら部分的な自作/共通化を検討
○ fromPromiseはラッパー関数1箇所に
限定する
15
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 16

![Page Image](https://bcdn.docswell.com/page/DJY4LDW87M.jpg)

neverthrowの導入方針
1. Linterによる制限
2. ラッパー関数の実装
苦手な関数やメソッドはLinterで制限
fromPromiseの冗長さを解決
●
●
ESLint / Oxlint
○
no-restricted-imports
○
no-restricted-properties
biome: GritQLを使用
●
ラッパー関数で冗長さを1箇所に閉じ込める
●
利用側はneverthrow標準のResultに近い体
験にする
○
戻り値に少しだけ工夫
16
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 17

![Page Image](https://bcdn.docswell.com/page/V7NY4699E8.jpg)

共通ラッパー関数の定義
方針
• 苦手な fromPromise の利用を1箇所に留める
• 戻り値 Promise&lt;Result&gt; で標準に寄せ、直感的に利用可能にする
import { ResultAsync } from &quot;neverthrow&quot;;
export function wrapAsyncCall&lt;T&gt;(
fn: () =&gt; Promise&lt;T&gt;,
cleanup?: () =&gt; void,
): ResultAsync&lt;T, Error&gt; {
return ResultAsync.fromPromise(
cleanup ? fn().finally(cleanup) : fn(),
(err) =&gt; (err instanceof Error ? err : new Error(String(err))),
);
}
17
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 18

![Page Image](https://bcdn.docswell.com/page/YJ9PQL2373.jpg)

wrapAsyncCallの利用側
ポイント
• fromPromiseと違い、コールバックを渡すだけで簡潔に記述できる
• 例外を意識せず、戻り値をResult型として関数型スタイルで扱える
const result = await wrapAsyncCall (() =&gt;
this.db.article. findUnique ({
where: { articleId: dbArticleId },
})
)
if (result.isErr()) {
return err(new ServerError (result.error))
}
18
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 19

![Page Image](https://bcdn.docswell.com/page/GJ8DGX5LJD.jpg)

04
まとめ
Copyright © 3-shake, Inc. All Rights Reserved.
19


# Page. 20

![Page Image](https://bcdn.docswell.com/page/LJLMG8YQER.jpg)

まとめ
コア要件の大半を満たすため、苦手な部分は制限・補完しつつ採用する
1. “not for me”は使い方の先入観
2. コア要件とグラデーション
●
●
●
先入観を疑ってみることが大事
コア要件の大半を満たすのであれば採用
○
Match中心の例だけを見て判断
○
自作すると保守コストが発生
○
パターンマッチや andTee などへの慣
れがコストに見えていた
○
ライブラリは叡智の結晶であり、自
前の実装より良いことが多い
とはいえ、“not for us”はあるかもしれない
●
提供されるAPIは使う・使わないを選択する
○
苦手なものは利用を制限してもいい
20
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 21

![Page Image](https://bcdn.docswell.com/page/47MYQ6DK7W.jpg)

おしまい
ご清聴いただき、ありがとうございました
スリーシェイク公式Note
Sreake事業部 採用情報
21
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 22

![Page Image](https://bcdn.docswell.com/page/P7R98P46E9.jpg)

付録：neverthrowはどの領域とマッチするか
●
Frontend：微妙
Backend：向いている
Reactであればデータ
フェッチを行うライブラ
リ（Tanstack Query,
SWR…）が状態管理込み
でエラーハンドリングす
る
●
●
副作用が比較的少ない
●
Fatalなエラーが起こりづ
らい
副作用が多い
●
比較的あり
DBや外部サービス
など
エラーハンドリングのミ
スは避けたい
●
副作用を扱う場合やエ
ラーをthrow以外で扱い
たい場合
●
denoで開発しやすくなっ
ているので、意外とあり
かもしれない
○
●
CLI：ちょっと向いている
○
Fatalなエラーが起
こりうるため
22
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 23

![Page Image](https://bcdn.docswell.com/page/PJXQ832D7X.jpg)

付録関連:TSに安易にResult型を導入しない方が良い
1. 境界でのトレードオフ
2. デバッグ体験の考慮
●
トレードオフはあるが、ラッパー等で実装コスト
は吸収可能
●
ブレークポイント派 vs プリントデバッグ派で許容
度が変わる
●
開発の本質は「境界」を作り安全な領域を確保す
ること
●
環境により避けた方が良いケースも存在する
Result型の導入を推奨できるケース
バックエンド
● バックエンド（APIや基盤など）は堅牢である方が望ましい
●
事業によっては堅牢さがより大事になってくるので、良いかも
●
ただし、両面TypeScriptなどTypeScriptを使いたい理由がある場合に限る
23
Copyright © 3-shake, Inc. All Rights Reserved.


# Page. 24

![Page Image](https://bcdn.docswell.com/page/3JK9KYMDJD.jpg)

参考文献
■ 仕様・公式ドキュメント
●
try...catch - JavaScript | MDN
●
Proposal: throws clause and throws type
(microsoft/TypeScript#13219)
●
neverthrow (GitHub)
○
Maintenance status #670
●
Symbol - JavaScript | MDN
●
no-restricted-imports - ESLint
●
Biome Linter Plugins (GritQL)
■ 実践・コミュニティ知見
●
●
例外処理（とほほのJava入門）
Type-safe error handling in TypeScript
（neverthrow開発者ブログ）
●
PBT+Result型で堅牢なビジネスロジックを
実現する (TSKaigi 2025)
●
「OSSがあるなら自作するな」は AI時代も正
しいか ── Build vs Adopt の新しい判断基
準
●
TypeScriptに安易にResult型を導入しない方
がいい - Qiita
24
Copyright © 3-shake, Inc. All Rights Reserved.


