TypeScript 2.2〜2.5までに追加された新機能:特集:TypeScript 2.0概説(2/2 ページ)
着々と進化を続けるTypeScript。バージョン2.2〜2.5までに、この言語がどのような進化を遂げたのかをざっくりと見てみよう。
new.target
new.targetメタプロパティはECMAScript 2015で導入されたもので、ある関数がコンストラクタとして(newを伴って)呼び出された時には、new.targetにはそのコンストラクタ関数がセットされる。newを伴わなかったときには、new.targetの値はundefinedとなる。
class Hoge {
constructor() {
console.log(new.target.name);
}
}
new Hoge(); // Hoge
文字列のenum
TypeScript 2.4では列挙型の値に文字列を指定できるようになっている。以下に例を示す。
enum SSIGNAL {
RED = "red",
BLUE = "blue",
YELLOW = "yellow"
}
enum NSIGNAL {
RED,
BLUE,
YELLOW
}
var ss = SSIGNAL.RED;
var ns = NSIGNAL.RED;
console.log(ss); // red
console.log(ns); // REDではなく0
console.log(SSIGNAL["RED"]); // REDではなくred
console.log(NSIGNAL[0]); // RED
SSIGNAL型は文字列のenum、NSIGNAL型は従来の列挙だ。上のコードでは、そのメンバを使ってコンソールに出力を行っている。
コード記述の面では、従来のenumは可読性を高めてくれるが、上のコードの出力例を見ると分かる通り、これは実際には整数値となってしまう(console.log(ns)の出力結果)。これに対して、文字列のenumを使うと、コード記述時にはenum型の値のように使える一方で、その値は文字列となっている。このため、データや出力を目視で確認するといったときには役立つだろう。
ただし、インデックスを指定して「SSIGNAL["RED"]」のようにしても、メンバである全て大文字の「RED」ではなく、その値である"red"が取得されている点には注意したい(その下の「NSIGNAL[0]」ではメンバであるREDが取得できている)。これは文字列のenumが次のようにトランスパイルされるからだ。見ての通り、単にSSIGNALにプロパティが設定されるようになっているだけだ。
var SSIGNAL;
(function (SSIGNAL) {
SSIGNAL["RED"] = "red";
SSIGNAL["BLUE"] = "blue";
SSIGNAL["YELLOW"] = "yellow";
})(SSIGNAL || (SSIGNAL = {}));
弱い型定義
ここでいう「弱い型」とは、その型の全てのプロパティがオプションとなっている型のこと。TypeScript 2.4で導入されている。例えば、以下のインタフェースReqは弱い型の例である。
interface Req {
url?: string,
method?: string,
data?: string
}
function someFunc(opt: Req) {
// 何か処理をする
}
var req1 = {
url: "http://www.atmarkit.co.jp",
data: "hogehoge"
}
var req2 = { // インタフェースReqのプロパティが何もない
message: "hello world"
}
var req3 = {
url: "http://www.atmarkit.co.jp",
message: "hello world"
}
someFunc(req1);
someFunc(req2); // エラー
someFunc(req3);
このコードのインタフェースReqは全てのプロパティがオプションとなっている。このような型がTypeScriptでは「弱い型」と呼ばれる。一方、3つの変数は、それぞれが独自のプロパティを持っている。これらを使ってsomeFunc関数を呼び出そうというのが上のコードだ。
TypeScript 2.4以降では、弱い型を必要とする部分(例:関数sumeFuncの引数)への代入時には、その弱い型で規定されているプロパティを何も含んでいないデータの代入が禁じられる。上の例だと、req1変数のプロパティは全てインタフェースReqで定められているプロパティと一致する(足りないものが1つあるが)。req2変数はインタフェースReqで規定されているプロパティを何も持たず、余計なプロパティを持っている。req3変数はインタフェースReqで定められているプロパティと、定められていないプロパティを持っている。これらの3つの変数を用いて、someFunc関数を呼び出そうとするとTypeScriptではreq2変数を使用したものだけがエラーとなる。
これは知らない間に間違った引数を指定して、何らかの処理を行おうとしてしまうバグを早期に発見するために使用できる。req3変数を指定した場合には、インタフェースReqに含まれていない要素については無視されるといった処理が行われることになるだろう(もっとも、それで動作に問題がないかは、実際のコードによるが)。
catch句での変数の省略
TypeScript 2.5からはtry/catchによる例外処理時に、catch句で例外情報を取得するための変数の記述を省略できるようになっている。以下に例を示す。これはJSONデータではないものをJSON.parseメソッドでパースしようとしているものだ。
var data = "not json data";
try {
var json = JSON.parse(data);
} catch { // 例外情報を取得するための変数を省略
console.log("couldn't parse");
}
トランスパイル後のコードではダミーの変数が挿入される。
var data = "not json data";
try {
var json = JSON.parse(data);
}
catch (_a) { // ダミーの変数が追加される
console.log("couldn't parse");
}
例外処理コードの記述時に、例外情報にアクセスする必要がないことが明らかであるときには便利に使えるだろう。
本稿ではバージョン2.2〜2.5にかけて、TypeScriptに追加された新機能を幾つか見てきた。次回は本稿で積み残している非同期イテレーションや非同期importなどの新機能について見ていくことにしよう。また、TypeScript 2.1の機能の中で拾い切れていないものについても取り上げる予定だ。
Copyright© Digital Advantage Corp. All Rights Reserved.