型定義書いていて『Union型に当てはまる場合はそのどれかだが、どれにも当てはまらなかったら"この型"』みたいなものを書きたくなるときがある。
例えば
type UnionA = 'tarou' | 'jirou' | 'saburou'
というUnion型があって、このUnionA
型に当てはまらなかったらstring
みたいなことを表現したくなったとする。
逆に言うとUnionA
の形式で補完が効いてほしいけど、補完以外のstringも受け付けたいみたいな欲求かもしれない。
const foo = '|' // ここで補完出すと 'tarou' | 'jirou' | 'saburou'が出て欲しいけど、別に'hogehoge~'みたいなstringでもOKみたいなわがまま型にするには…
人間的にはこう書けばいけそうな気がして書くがうまくいかない…
type UnionOrString = UnionA | string const foo: UnionOrString = '|' // 補完が効かない!
そんな〜って気持ちになって破滅する。
LiteralUnion
たまたまSindre氏の型定義集のライブラリ眺めてたところ上記の問題を解決できる便利型が転がっていた。
export type LiteralUnion< LiteralType extends BaseType, BaseType extends Primitive > = LiteralType | (BaseType & {_?: never});
これを使うと…
Issue
Issueはここみたいだけどコンパイラ的に解釈できないのでこういう型をいまのところは経由しないとダメみたい。
わりとこのわがままなUnion型をやりたい人は多そうな気がしているけど、ググラビリティが低すぎてみんなたどり着けていないのでは……という気がしている。
この記事もそういう意味ではたどり着けないのかもしれない。ユニオン型orなにかの型みたいなことを、もっとわかりやすく直接脳で解釈できるような言葉で書くの難しい気がする。