SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

ますます便利になるTypeScript! バージョン3からの変更点と総まとめ

TypeScriptバージョン3から5.2までのアップデート内容まとめ ──型の絞り込みについて解説

ますます便利になるTypeScript! バージョン3からの変更点と総まとめ 第4回

アサーション関数

 ここまで、制御フロー分析に伴う型の絞り込みを紹介してきました。次に、制御フロー分析とは別の型の絞り込みを紹介します。それは、アサーション関数です。

例外発生関数の利用

 例えば、リスト6の(1)のreturnJSON.result.msgが存在しない場合にエラーを発生させる関数として、リスト12のassertResultMsgIsString()を用意したとします。その上で、extractResult()関数をリスト12のように書き換えたとします。

リスト12:条件判定にエラー発生を利用した関数
function assertResultMsgIsString(result: unknown) {
  if(result == null || typeof result != "object" || !("msg" in result) || typeof result.msg != "string") {  // (1)
    throw Error();  // (2)
  }
}
function extractResult(returnJSON: ReturnJSON): string {
  let result = "通信失敗";
  if(returnJSON.status == 1) {
    let result = "データ取得失敗";
    assertResultMsgIsString(returnJSON.result);  // (3)
    result = returnJSON.result.msg;  // (4)
  }
  return result;
}

 リスト12の(1)はリスト6の(1)のifの内容を反転させた内容となっており、この場合、引数のresultにはmsgは存在しないとして、(2)でエラーを発生させています。そして、extractResult()関数内では、このassertResultMsgIsString()関数を(3)で実行して、msgが存在するかどうかの判定として利用しています。つまり、制御フロー分析の代わりとして利用しています。

 しかし、ここで問題となるのは(4)です。(3)でエラーが発生しなかったということは、(4)の段階でreturnJSON.result.msgは存在するはずです。すなわち、ここで型の絞り込みが行われければならないはずです。しかし、TypeScriptのコンパイラはこのことを認識できず、図6のエラーとなってしまいます。

図6: エラー発生では型の絞り込みが働かない
図6: エラー発生では型の絞り込みが働かない

asserts構文

 この問題を解決するためにバージョン3.7で導入されたのがassertsキーワードを利用したアサーション関数です。リスト12のassertResultMsgIsString()関数の戻り値の型として、リスト13の(2)の記述をするだけで、図6のエラーは表示されなくなります。この(2)の意味するところは、関数からエラーが発生しなければ、引数であるresultは(1)のResultObj型であることを保証する、という意味です。これにより、型の絞り込みが働くようになります。

リスト13:アサーション関数
interface ResultObj {  // (1)
  msg: string;
}
function assertResultMsgIsString(result: unknown): asserts result is ResultObj {  // (2)
  :
}

satisfies演算子

 最後に紹介するのは、satisfies演算子です。

ユニオン型の問題

 例えば、リスト14の(1)のようなReturnJSON型を考えます。このReturnJSON型は、各プロパティがユニオン型で定義されています。そして、そのReturnJSON型のオブジェクトリテラルとして、(2)のrJsonを定義し、(3)でそのプロパティresultのErrorオブジェクト内のプロパティmessageにアクセスしています。

リスト14:ユニオン型をプロパティとするオブジェクト型リテラル
interface ReturnJSON {  // (1)
  status: 0 | 1;
  result: string | Error;
}
const rJson: ReturnJSON = {  // (2)
  status: 0,
  result: new Error("ダメでした")
};
const error = rJson.result.message;  // (3)

 このコードは一見、問題ないように思えますが、実は、(3)で図7のエラーとなります。これは、エラーメッセージの通り、resultがstringとErrorのユニオン型であるために起こるエラーです。

図7:ユニオン型ゆえのエラー
図7:ユニオン型ゆえのエラー

satisfiesによる型指定

 この問題を解決するためにバージョン4.9で導入されたのがsatisfies演算子による型指定です。リスト14の(2)のrJsonをリスト15のように定義すると、(3)のエラーは解消されます。

リスト15:satisfiesによる型指定
const rJson = {
  status: 0,
  result: new Error("ダメでした")
} satisfies ReturnJSON;

 このsatisfiesによる型指定を行うことで、リスト14の(2)の型指定とは違い、rJsonの構成要素が優先され、resultがErrorオブジェクトとして扱われる一方で、例えば、othersのようなReturnJSONに定義されていないプロパティをrJsonに定義しようとすると、エラーとなります。これは、satisfiesによる型指定では、オブジェクトのプロパティ構成がReturnJSONに一致するように緩く判定されるからです。

まとめ

 TypeScriptのバージョン5.2までに導入された新機能をテーマごとに紹介する本連載の第4回目はいかがでしたでしょうか。

 今回は、型の絞り込みに関するアップデートを紹介しました。次回は、クラス構文に関する新しい仕組みを紹介します。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
ますます便利になるTypeScript! バージョン3からの変更点と総まとめ連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 齊藤 新三(サイトウ シンゾウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。Web系製作会社のシステム部門、SI会社を経てフリーランスとして独立。屋号はSarva(サルヴァ)。HAL大阪の非常勤講師を兼務。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/19331 2024/04/19 11:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー