この記事はRust+SvelteKit+CDK で RSS 要約アプリを作ってみる Advent Calendar 2025の 23 日目の記事になります。
また、筆者が属している株式会社野村総合研究所のアドベントカレンダーもあるので、ぜひ購読ください。
はじめに
Rust を勉強する上で特徴的と感じたのはOptionやResultといった、「処理の結果を格納する型」でした。普段触る TypeScript と比較して、慣れるのに時間がかかるものの、非常に便利な仕組みだと感じました。
Option
Rust では、値が存在するかどうかを表現する型としてOptionがあります。
TypeScript では、例えばある値が、stringの値を取ることが想定されるが、初期状態ではundefinedである、もしくは処理が中断する可能性がある場合、string | undefinedのように型を定義する必要があります。
let name: string | undefined;
Rust では、この状態を標準で表現するための型としてOptionを用意しています。
let name: Option<String>;
Option<T>は内部に2種類の値を持ちます。Some(T)とNoneです。Some(T)は値が存在する場合、Noneは値が存在しない場合を表します(そのため、同時にどちらにも値が存在する、は基本的にあり得ません)。
Option<T>からT型の値を抽出するにはunwrap()を使います。ただし、このメソッドはSomeから抽出する分には成功しますがNoneから抽出する分には失敗します。
Result
Optionは値があるかないかを表現するのに対して、もう少し踏み込んで「なぜないのか(=エラーの詳細)」も含めたのがResult型になります。
ResultはOk(T)とErr(E)の 2 種類の値を持ち、Ok(T)は成功したことを表し、Err(E)は失敗したことを表します。Ok(T)からT型の値を抽出することも可能ですし、Err(E)からE型の値を抽出することも可能です。
// 成功時と失敗時の型を指定
fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
// 失敗時はErrでラップして返す
Err("0で割ることはできません".to_string())
} else {
// 成功時はOkでラップして返す
Ok(a / b)
}
}
この仕組みは TypeScript の標準とは大きく異なります。TS では例外を発生させることでエラーを表現します。一方で、どの関数がどんな例外を投げうるか、というのは表現できません(Java にはthrowsがある)。また、catchしたとしてその型は推測不能であり、型チェックが困難です(instanceofを使って型を特定する必要があります)。
パターンマッチングとの組み合わせ
成功したかどうかでマッチングしたり、処理を続行もしくは中断したりしたい場合は、matchやif letを組み合わせて使用します。
let result = divide(10, 2);
match result {
Ok(val) => println!("割り算の結果: {}", val),
Err(msg) => println!("エラー: {}", msg),
}
// エラーハンドリングを簡潔に書く
let Ok(val) = devide(10, 0) else {
println!("計算できませんでした");
return;
};
実際、OptionやResultそのものの寿命は長くなく、matchやif let、let elseで抽出とエラーハンドリングを行うことが一般的かと思います。