【TypeScript】作成した型の絞り込みを行う
技術的なメモです。
基本的な型の絞り込み
型の絞りこみは TypeScript でなくとも行えますが、
その絞り込みを通知することができます。
if節内部でホバーしてみると分かります。
function juice(fruit: 'apple' | 'orange' | 'grape') { if (fruit === 'apple') { // ★ fruit が apple であることが認識できる } }
この恩恵を与れる簡単な利用方法です。
タグ付きユニオン型
APIの処理結果など
- ユニオン型のそれぞれの構造が大きく変わる
場合に利用できます。
type Result = Success | Error type Success = { data: string } type Error = { error_message: string, data: string } fucntion show(result: Result) { // Error型のチェック // この時点ではSuccess型の可能性があるため、Successにないプロパティの参照は許されない。 // in を使ってプロパティが存在するかを確認する if ("error_message" in result) { // ここでError型と推論される } }
in
を使った構成でなく、ユニオン型の構成要素に「識別するためのタグ」をつけます。
type Result = Success | Error type Success = { kind: 'success', data: string } type Error = { kind: 'error', error_message: string, data: string } fucntion show(result: Result) { // Error型のチェック // Success/Errorどちらも kind を共通してプロパティに持っているため、 // result.kindによるアクセスが行える if (result.kind === 'error') { // ここでError型と推論される } }
T | should have been removed
の改善
const arr = [1,2,3,null]; arr.filter(x => x).map(x => x*2);
このコードは map
内でエラーになります。
変数 arr
は number | null
型であり filter
では null
を除外しているのですが、
これが認識されず引き続き number | null
型とみなされています。
そのため null
との演算が行えずエラーとなります。
このように標準の組み込み関数では除外したはずの型がコンパイラは十分に認識されないことがあります。
この場合、ユーザー型ガードを利用します。
function isNotNull<T>(x: T): x is Exclude<T, null> { return x != null } const arr = [1,2,3,null]; arr.filter(isNotNull).map(x => x*2)
自作関数 isNotNull
で null
の除外を宣言したことで、filter
の後では null
の可能性がないことを認識してくれます。
移行済(JavaScriptに毛が生えたような any
まみれ)のコードで活かす機会は少ないのですが...