SHOEISHA iD

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

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

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

TypeScriptの根幹「型システム」、バージョン3から5.2までの変更点を解説!

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

  • X ポスト
  • このエントリーをはてなブックマークに追加

constキーワードに関する新機能

 次に紹介するのはconstキーワードに関する新機能です。constは、変数宣言の時に利用しますが、ここでの使い方は、型指定において使われるconstです。具体的に見ていきましょう。

constアサーション

 例えば、["RED", "GREEN", "BLUE"]というデータは、RGB色の文字列を、配列として表現したものです。これを変数に代入したリスト4のコードでは、その変数rgbのデータ型は、型推論からstring[]となります。そのため、rgbにYELLOなどの文字列を簡単に追加できてしまいます。

リスト4:変数rgbの定義
const rgb = ["RED", "GREEN", "BLUE"];

 これを防ぐために、例えば、リスト5のコードで定義される読み取り専用のReadonlyRGBなどを用意し、あらかじめ型指定する方法もあります。こうすることで、確かに、rgbには文字列を追加できなくなります。

リスト5:型指定も含めた変数rgbの定義
type ReadonlyRGB = readonly string[];
const rgb: ReadonlyRGB = ["RED", "GREEN", "BLUE"];

 一方で、もっと簡単な方法がリスト6のコードです。as constを付け加えるだけで、簡単に読み取り専用のデータが出来上がります。もちろん、これは、配列やタプルだけでなく、プリミティブな変数やオブジェクトにも適用できます。この仕組みをconstアサーションといい、バージョン3.4で導入されました。

リスト6:as constの利用例
const rgb = ["RED", "GREEN", "BLUE"] as const;

constアサーションの場合の型推論

 このconstアサーションによるメリットは、単に読み取り専用になるだけではなく、型推論によるその変数のデータ型が狭まることです。例えば、ReadonlyRGBで型定義したrgbの場合は、読み取り専用とはいえ、あくまでそのデータ型はstring[]です。一方、as constで読み取り専用にしたrgbのデータ型は、図1のように、代入した値そのものとなります。

図1:as constを適用した変数のデータ型
図1:as constを適用した変数のデータ型

 そのため、例えば、GREENという文字列を表すrgb[1]のデータ型も、stringではなく、"GREEN"型となります。これは、プリミティブ型でも同じであり、例えば、リスト7のコードで定義した変数msgのデータ型は、string型ではなく"hello"型となります。

リスト7:as constをプリミティブ型に適用した例
const msg = "hello" as const;

ジェネリクスへのconst指定

 このconstによる型を狭める仕組みは、さらに拡張され、バージョン5.0でジェネリクスにも利用できるようになっています。これは、例えば、リスト8のようなコードです。

リスト8:ジェネリクスにconstを適用した例
type RgbO = {
  rgb: readonly string[];
}
function extractRGB<const Colors extends RgbO>(colors: Colors): Colors["rgb"] {
  return colors.rgb;
}
const extractedRgb = extractRGB({  // (1)
  rgb: ["RED", "GREEN", "BLUE"],  // (2)
  colorAdd: "YELLO"  // (2)
});

 関数extractRGB()は、引数オブジェクトに含まれるrgbプロパティの配列を抽出する関数です。そのため、引数の型であるColorsは、必ず読み取り専用String配列であるrgbプロパティが含まれている必要があり、それをジェネリクスのextends RgbOで指定しています。ただし、そのジェネリクスのColorsにはconstキーワードが付与されています。

 このように定義した関数に対して、リスト8の(2)のような引数を渡すと、その引数はas constが付与されたのと同じような働きをします。結果、(1)の変数extractedRgbの型はString[]ではなく、図2のように、引数のrgbプロパティのデータと同一、すなわち、["RED", "GREEN", "BLUE"]型となります。

図2:ジェネリクスにconstを適用した場合
図2:ジェネリクスにconstを適用した場合

 これが、ジェネリクスにconstのないColorsの場合は、図3のようにString[]と型推論されてしまいます。

図3:ジェネリクスにconstを適用していない場合
図3:ジェネリクスにconstを適用していない場合

 なお、この仕組みが働くのは、関数の引数に直接リテラルを記述した場合です。リスト8の(2)の引数を、例えば変数colorsとして定義し、次のように、その変数を引数として渡した場合は、extractedRgbのデータ型はString[]と型推論されるので注意してください。

const extractedRgb = extractRGB(colors);

型定義におけるテンプレート文字列

 次に紹介するのは、リテラル型にテンプレート文字列が利用できるようになったことです。具体的にみていきましょう。

テンプレート文字列によるリテラル型

 リテラル型というのは、前節でも登場しており、リスト7のmsgの"hello"型は、リテラル型になります。ただ、通常は、リスト9の(1)や(2)の型定義のように、ユニオン型と組合せます。

リスト9:リテラル型の例
type BlankSpace = "margin" | "padding";  // (1)
type Position = "top" | "bottom" | "start" | "end";  // (2)

 こうすると、例えば、BlankSpace型の変数には、文字列のmarginかpadding以外は代入できなくなります。例えば、以下のコードはエラーとなるため、綴りミスなどを防げます。

const bs: BlankSpace = "margine";

 ここで、リスト9の(1)と(2)を組合せ、例えば、margin-topのようなリテラル型としてBlankSpaceAndPositionを作りたいとします。これまでならば、リスト9の(1)や(2)と同様に、組合せた文字列を列挙したユニオン型の型定義を記述する必要がありました。これが、バージョン4.1でテンプレート文字列を型定義に利用できるようになり、リスト10のコードで組合せの型定義ができるようになりました。これを、テンプレート文字列型といいます。

リスト10:テンプレート文字列型の例
type BlankSpaceAndPosition = `${BlankSpace}-${Position}`;

テンプレート文字列型と相性がいい新しい型操作

 テンプレート文字列型の導入と同時に、つまり、同じくバージョン4.1で、新しい型操作が導入されました。それが、表1の4個です。

表1:テンプレート文字列型と同時に導入された型操作
型操作 内容
Uppercase 大文字へ変換
Lowercase 小文字へ変換
Capitalize 最初の文字を大文字へ変換
Uncapitalize 最初の文字を小文字変換

 例えば、リスト10のBlankSpaceAndPositionを、リスト11のように定義すると、MarginTopのようなキャメル記法のリテラル型が出来上がります。

リスト11:テンプレート文字列型と型操作を組合せた例
type BlankSpaceAndPosition = `${Capitalize<BlankSpace>}${Capitalize<Position>}`;

次のページ
Mapped型での再マッピング

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

  • X ポスト
  • このエントリーをはてなブックマークに追加
ますます便利になるTypeScript! バージョン3からの変更点と総まとめ連載記事一覧

もっと読む

この記事の著者

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

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 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本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

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

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

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/19309 2024/04/17 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング