Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
TypeScriptのエラー処理(ES2022の新機能を添えて)
Search
あけの
July 03, 2022
Programming
3.1k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
TypeScriptのエラー処理(ES2022の新機能を添えて)
あけの
July 03, 2022
More Decks by あけの
See All by あけの
Reactハンズオンラーニングを読んだので感想を語る
akeno
1
740
oapi-codegenを使ってみた
akeno
0
3k
こんな案件は嫌だ(※個人の感想です)
akeno
1
250
SQLアンチパターンから学ぶテーブル設計
akeno
0
800
VSCode Remote Containers のすすめ
akeno
0
380
設計とテストの必要性について考える
akeno
1
320
Other Decks in Programming
See All in Programming
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
190
Workers Cache を知る
syumai
0
370
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
350
AI-Powered Domain-Driven Design
ziobrando
0
190
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
880
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
190
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
180
[2026-10-09]一枚の布で作らなくてもいい。 信頼性は「パッチワーク」で紡がれる~既存の運用と新しい可能性をつなぎ合わせてきたCREの話~
tosite
0
110
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
6.8k
sbt 2.0: takeoff
eed3si9n
0
170
golang-bob.pdf
iwatsukayura
0
130
Optunaを作ったときにやりたかったこと、その後 (2026/10/16, Optuna Meetup #3)
iwiwi
2
1.2k
Featured
See All Featured
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.2k
Automating Front-end Workflow
addyosmani
1369
210k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
540
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Code Review Best Practice
trishagee
74
20k
[SF Ruby Conf 2025] Rails X
palkan
3
1.5k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.6k
Into the Great Unknown - MozCon
thekraken
41
2.8k
Build your cross-platform service in a week with App Engine
jlugia
234
19k
BBQ
matthewcrist
90
10k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
500
Transcript
@akeno_0810 2022.07.03 TypeScriptのエラー処理 (ES2022の新機能を添えて) Web Creator Meetup in KANSAI #2
自己紹介 About me akeno (@akeno_0810) Webエンジニア歴2年くらい Rust, API/コード設計, DevOps/開発の効率化 触っている技術
最近興味のある分野
話すこと About this talk f TypeScriptのエラー処理の紹g f エラーを返り値とする場合の型のハマりどこe f ES2022のHard
Privatb f ES2022のError Causb f 追加情報を持たせていい感じに出力する
TypeScriptのエラー処理
TypeScriptのエラー処理 エラー処理 →ある関数で処理続行不可能になった場合にどうハンドリングするか? 言語によって差がある Java→Exceptionをthrowする Rust→Result型やOption型を用いる Go→返り値でエラーを返す TypeScriptではどうするのがいいのか? try throw
new catch { HogeException(); } (HogeException e) { e.printStackTrace(); } res, err := HogeFunc() err != { fmt.Errorf(“%v”, err) } if nil fn hogeFunc() -> Result<i32, ParseIntError> { Err() } let result = hogeFunc() match result { Ok(n) => !( , n), Err(e) => !( , e), } println println "n is {}" "Error: {}"
TypeScriptのエラー処理 https://qiita.com/kabosu3d/items/680728362314f51bdcb0 XP nullやundefinedを返り値とする function : | if return return
() { (error) { ; } “success”; } hoge string null null Goo 何も考えないでいいので 呼び出し元でnullを考慮する必要があるので安全 Ba エラーが起こった以上の情報が得られない
TypeScriptのエラー処理 2. 例外をスローする GooF 詳細なエラー情報を呼び出し元に渡せる BaF 呼び出し元からはエラーが起こるかどうか読み取れなA
どのようなエラーが返ってくるかわからなA try-catchを忘れると永遠にcatchされずに落ちる function : if throw new return try catch if instanceof () { (error) { (); } “success”; } { (); } (e) { (e ){ console. (e); } } hoge hoge Error log string Error
TypeScriptのエラー処理 3. エラーを返り値とする Gooc d 詳細なエラー情報を呼び出し元に渡せB d 呼び出し元は返ってくるエラーを考慮する必要がある Bac d
エラーを返す側も呼び出し側も記述が冗長 function : | if return new return const = if instanceof () { (error) { (); } “success”; } (); (h ) { console. (e); } hoge Error hoge Error log string Error h
TypeScriptのエラー処理 4. Option/Result型を用いる Goot 呼び出し元は返ってくるエラーを考慮する必要がある Bat 言語でのサポートがなD
アプリケーション全体がライブラリに依存する
TypeScriptのエラー処理 nw nullやundefinedを返り値とすq w 例外をスローする エラーの詳細度や型安全の観点から厳しい 4. Option/Result型を用いる 特定のライブラリにアプリケーション全体が依存する状況は避けたい 個人的には殆どの場合で
3. エラーを返り値とする を使っている。
エラーを返り値とする場合の 型のハマりどころ
エラーを返り値とする場合の型のハマりどころ エラーを返り値とすることで型安全…と思いきやそうでもない エラー定義の方法によっては型の縛りが効かない場合がある class extends class extends return if instanceof
== { } { } (): HogeError { (); } ( () ) { console. (“HogeError FugaError”) } HogeError FugaError hoge FugaError hoge FugaError log Error Error function // エラーにならない functionの返り値の型はStructural Subtyping(ダックタイピング) によって判断される →お互いの実装が同じなので型を満たしていると判断される →違う型を意図していたが同じ型として扱われた instanceofは返り値のプロトタイプチェーンを見ている →実際返ってきているのはFugaErrorなのでtrue 型が壊れている状態
エラーを返り値とする場合の型のハマりどころ class extends readonly = class extends readonly = function
: return { // “HogeError”型 “HogeError”; } { // “FugaError”型 “FugaError”; } () { (); } HogeError FugaError hoge HogeError FugaError Error Error className className // エラー! 解決策 各クラスにreadonlyの文字列を持たせる →型推論によって`className`の型が絞り込まれる 関数で使用する際にその部分の型が異なる と判定されてコンパイルエラーとなる
ES2022のHard Private
ES2022のHard Private class extends readonly = class extends readonly =
{ “HogeError”; } { “PiyoError”; } HogeError PiyoError HogeError Error // “HogeError”型 // 継承している // “PiyoError”型 ... 定義できない! className className さらなる問題 継承元で定義されている型を継承先で変更できな string型で指定すると型判定ができない 困った… →継承先にプロパティを渡さなければ解決する! (ちなみにSoft PrivateではJavaScriptに変換された 際の挙動が異なるため実現できない)
ES2022のHard Private class extends readonly = class extends readonly =
{ “HogeError”; } { “PiyoError”; } HogeError PiyoError HogeError Error // “HogeError”型 // 継承している // “PiyoError”型が定義できる! #className #className Hard Privateを用いた解決 (https://ics.media/entry/220610/) Hard Private ES2022で追加されたプライベートプロパティの宣言 TypeScriptとしてはv3.8から使えた Soft Private のような宣言 この2つはトランスパイルの結果が異なる 継承を用いても型安全にエラーを処理できる! private hoge = “hoge”
ES2022のError Cause
ES2022のError Cause interface ?: interface ?: interface new ?: ?:
: ?: ?: : { ; } { ; } { ( , ) ; ( , ) ; } ErrorOptions Error Error Error ErrorConstructor ErrorOptions Error ErrorOptions Error cause cause message options message options string string ES2022のエラー周りの型定義 interface : : ?: interface new ?: : ?: : readonly : declare var : { ; ; ; } { ( ) ; ( ) ; ; } Error ; Error ErrorConstructor Error Error Error ErrorConstructor name message stack message message prototype string string string string string ちなみにES5ではこう コンストラクタにOptionsが渡せるようになっている
ES2022のError Cause つまりこういうことができる // ES2022 error cause // throw error
const = : : => const ... = if ! return ... return try throw new new catch if instanceof ( ) { { , , , } e; ( cause) { rest, name: e.name, msg: e.message}; {name: name, msg: message, cause: (cause)}; } { ( , {cause: ( )}); } (e) { (e ) { console. ( . ( (e))); } } printErr Error CustomErr printErr ResError ReqError ResError log printErr e name message cause rest JSON stringify "a" "b" エラーの入れ¥ 再帰的に取り出 いい感じに出力 深い階層で起こったエラー をWrapして、上の階層に 返すことが容易になった {"name":"Error","msg":"a","cause":{"name":"Error","msg":"b"}}
追加情報を持たせていい感じにする
追加情報を持たせていい感じにする export class extends : constructor : : : :
= { < , >; ( , { , } { ; < , > } ) { (message, { cause }); .obj obj; } } CustomError Record Error Record Error string unknown string string unknown super this obj message cause obj cause obj エラーには追加情報がつきもの ファイル名や実行された際の引数等、message: string で表現するには限界がある アプリケーション側でカスタムしたエラーを定義して、それを継承していく
追加情報を持たせていい感じにする 出力が面倒になってくるのでロギングライブラリを用いる https://github.com/pinojs/pino new new const = => ( ,
{ cause: ( ), obj: {hoge: } }); ({ formatters: { : ( , ) ({ level: label, }), }, browser: { asObject: , }, }); logger. (e); logger. ({e}); ResError ReqError pino level error error "a" "b" "huga" logger true label _ { time: 1656824412503, level: 50, obj: { hoge: "huga" } } { time: 1656824412503, level: 50, e: Error: a at file:///Users/**masked**/Projects/ts-error-demo/main.ts:37:11 Caused by Error: b at file:///Users/**masked**/Projects/ts-error-demo/main.ts:37:37 } errortraceとobjを一緒に出せたはずなのだが、 出来ない… with deno
追加情報を持たせていい感じにする { : , : , : , : ,
: { : , : , : , : { : } }, : } "level" "time" 1656825987852 "pid" 50218 "hostname" "err" "type" "message" "stack" \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n "obj" "hoge" "msg" "error" "**masked**" "ResError" "a: b" "Error: a at Object.<anonymous> (/Users/**masked**/Projects/ts-error-demo-node/dist/main.js:31:11) at Module._compile (node:internal/modules/cjs/loader:1105:14) at Module._extensions..js (node:internal/modules/cjs/loader:1159:10) at Module.load (node:internal/modules/cjs/loader:981:32) at Module._load (node:internal/modules/cjs/loader:827:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12) at node:internal/main/run_main_module:17:47 caused by: Error: b at Object.<anonymous> (/Users/**masked**/Projects/ts-error-demo-node/dist/main.js:31:47) at Module._compile (node:internal/modules/cjs/loader:1105:14) at Module._extensions..js (node:internal/modules/cjs/loader:1159:10) at Module.load (node:internal/modules/cjs/loader:981:32) at Module._load (node:internal/modules/cjs/loader:827:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12) at node:internal/main/run_main_module:17:47" "huga" "a" with node.js
まとめ
Thank you! まとめ TypeScriptのエラー処理には実装の選択肢があ 型安全かつ使うハードルの低いものを選びたc TypeScriptの型は実装ベースで判断され
型を明確に異なるものにしたい場合は工夫が必0 ES2022(TS3.8)で入ったHard Privateが使え ES2022でError Causeが入っf エラーの原因を保持しやすくなった エラー処理は雑になりやすい部分なので、 安全かつ後から原因を追跡できるように実装していきたい