www.oreilly.com
Returning Null
- Pros
- Cons
- 「なぜ失敗したか」の情報を欠く
- 「日付のパースに失敗しました」よりは「Ymdで入力してください」の方が親切
Throwing Exceptions
- Pros
- Cons
- JavaScriptにはcatchのガードがないので単一のcatchの中でif-then-elseしないといけない
catch(e instanceof DateIsInTheFutureError)
- TypeScriptでは、例外は関数のシグネチャとして扱われない
- docコメントで、送出されうる例外を示すことはできる
- が、TSでこれを検査例外扱いしたりすることはできない
class MyError extends Error { }
@throws{MyError}
function hoge(): number {
const rand = Math.random()
if (rand < 0.5) {
throw new MyError
}
return 1;
}
hoge();
Returning Exceptions
- 正常値と例外のunion typesを返す
- Pros
- Cons
- 冗長
- 呼び出し側は、戻り値を受け取って即座にエラー判定しないといけない
- 同じようなエラー判定コードまみれになる
if (res instanceof Error) { return res; }
The Option Type
Option<T>
,Try<T>
,Either<T,U>
とかの紹介
- 概念自体は知ってるので略
- 自作しようの巻
- 書籍のものがテキトーすぎたので自前で書いた
type NotNullOrUndefined = {}
class Just<T extends NotNullOrUndefined>{
constructor(private value: T) { }
flatMap(f: (value: T) => Nothing): Nothing
flatMap<U extends NotNullOrUndefined>(f: (value: T) => Just<U>): Just<U>
flatMap<U>(f: (value: T) => Maybe<U>): Maybe<U>
{
return f(this.value)
}
getOrElse(_: T): T {
return this.value
}
}
class Nothing {
flatMap(_: (value: never) => Nothing): Nothing
flatMap<U extends NotNullOrUndefined>(_: (value: never) => Just<U>): Nothing
flatMap<U>(_: (value: never) => Maybe<U>): Nothing
flatMap<U>(_: (value: never) => Nothing|Just<U>|Maybe<U>): Nothing
{
return this
}
getOrElse<T extends NotNullOrUndefined>(value: T): T {
return value
}
}
type Maybe<T> = T extends NotNullOrUndefined ? Just<T> : Nothing
function Maybe<T extends NotNullOrUndefined>(value: T): Just<T>
function Maybe(value: null | undefined): Nothing
function Maybe<T>(value: T): Maybe<T>
function Maybe<T>(value: T): Just<T>|Nothing|Maybe<T>
{
if (value == null) {
return new Nothing
}
return new Just(value)
}
const a = new Just(null)
const b = new Just(undefined)
const c = new Just(1)
const d = new Nothing
const just = Maybe(1)
const nothing = Maybe(null)
const maybe = Maybe(Math.random() < 0.5 ? null : 1)
const maybe2 = Maybe(Math.random() < 0.5 ? 's' : 1)
const e = just.flatMap((_: number) => new Nothing)
const f = just.flatMap((num: number) => new Just(num * num))
const g = just.flatMap((_: number) => new Just('s'))
const h = nothing.flatMap((_: number) => new Nothing)
const i = nothing.flatMap((num: number) => new Just(num * num))
const j = e.getOrElse(true)
const k = f.getOrElse(true)
const l = g.getOrElse(true)
const m = h.getOrElse(true)
const n = i.getOrElse(true)
- Conditional Typesを使って
Just<string|number>
を Just<string>|Just<number>
にバラすこともできる
- が、
flatMap<U>
が対応できないのでやめた