ことのはじめ
TypeScript初心者数名でチームを組み、アプリ開発を行なっていたところ、オブジェクトのプロパティの型定義や関数の引数で以下の記述が混在していた。
type Hoge = {
fuga?: number
}
type Foo = {
bar: number | undefined
}
当時は「?」を使うのが省略記法で、ただの表記揺れかと思い、統一感がないので「?」を使う方に統一しましょう的な感じで話を終えていたが、調べてみたらちゃんと違いがあったので、備忘がてらメモ。
違い
まず、前者はOptional Propertyである。その名の通り、プロパティ自体が任意(オプショナル)となるので、プロパティを省略することができる。つまり、
type Hoge = {
fuga?: number
}
const hoge1: Hoge = { fuga: 0 } // ⭕️
const hoge2: Hoge = { fuga: undefined } // ⭕️
const hoge3: Hoge = {} // ⭕️
と書ける。
それに対し、後者はUnion型である。プロパティの型がnumberまたはundefinedであるということが明記されているのであって、プロパティを省略することはできない。よって、
type Foo = {
bar: number | undefined
}
const foo1: Foo = { bar: 0 } // ⭕️
const foo2: Foo = { bar: undefined } // ⭕️
const foo3: Foo = {} // ❌
となる。
所感
では違いを理解したところで、使い分けについて考えたみたが、簡潔かつ利便性が高いという理由で、やっぱり基本的にOptional Propertyで良くない?と思った。「プロパティが存在しない」と「明示的にundefined」の区別をつけたい場合がUnion型の出番かと思われるが、かなり限定的なケースかと思慮。TypeScript上級者さん達はどう使い分けてるのだろうか...?