TypeScript 2.6 変更点と注意点
TypeScript2.6が出たので変更点を記載
RCからほぼ変更点がない。
Strict Function Typeフラグの導入
--strictFunctionTypes
というフラグが導入される。
このフラグは--strict
フラグに内包されており、--strict
の場合は自動でONになるが、
--strictFunctionTypes
をfalse
にすることで個別にOFFにすることもできる。
動作
関数の引数に対するVarianceの動作を変更する。
TypeScriptの関数のVarianceについては以前下のスライドで説明したので参照。
今回の--strictFunctionTypes
フラグがONになると、関数がBivariantではなくてContravariantになる。
つまり以下のような代入が許可されなくなる。
class Animal { ... } class Dog extends Animal { ... } declare let acceptAnimal: (animal: Animal) => void; declare let acceptDog: (dog: Dog) => void; acceptAnimal = acceptDog // Error acceptDog = acceptAnimal // OK!
またこの変換が不可能になると、以下のように総称型の代入規則が変化する。
class Animal { ... } class Dog extends Animal { ... } class GenericAnimal<T> { someFn(animal: T) {} } delcare let animalAnimal: GenericAnimal<Animal>; delcare let animalDog: GenericAnimal<Dog>; animalAnimal = animalDog // Error. animalDog = animalAnimal // OK. // someFn(animal: Dog) // someFn(animal: Animal)
これは関数がBivariantではなくなるために起こる。
Animal
を受け取る関数にDog
を受け取る関数を渡すと、Dog
がAnimal
の派生型である限り、
Dog
固有の処理を行っていた場合にRuntimeエラーを起こす可能性が高く危険な代入になるが、
Animal
を受け取る関数にDog
を渡すのは安全であるため、このような変換規則になる。
そのため外から見るとDog <= Animal
の変換をしているように見えるが、関数の引数という文脈で考えると、
この変換はAnimal <= Dog
の変換となり自然に見える。
注意
--strict
モードでこの機能が有効になるため、--strict
オプションをONにしているコードに対しては、
この変換規則が強制的に適用される。
なので今まで逆の変換を行っているコードはすべてコンパイルエラーになる。
それが困る場合は--strictFunctionTypes false
でOFFにすることができる。
タグ付きテンプレートリテラルをキャッシュするようになった
タイトル通り。
一度作ったテンプレートリテラルオブジェクトをキャッシュするようになったので、以下のコードがtrue
になるようになった。
export function id(x: TemplateStringsArray) { return x; } export function templateObjectFactory() { return id`hello world`; } let result = templateObjectFactory() === templateObjectFactory(); // true in TS 2.6
Emit Result in v2.5
"use strict"; exports.__esModule = true; function id(x) { return x; } exports.id = id; function templateObjectFactory() { return (_a = ["hello world"], _a.raw = ["hello world"], id(_a)); var _a; } exports.templateObjectFactory = templateObjectFactory; var result = templateObjectFactory() === templateObjectFactory(); // true in TS 2.6
Emit Result in v2.6
"use strict"; var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } return cooked; }; function id(x) { return x; } var _a; function templateObjectFactory() { return id(_a || (_a = __makeTemplateObject(["hello world"], ["hello world"]))); } var result = templateObjectFactory() === templateObjectFactory();
ここに注目
// v2.5 function templateObjectFactory() { return (_a = ["hello world"], _a.raw = ["hello world"], id(_a)); var _a; } // v2.6 var _a; function templateObjectFactory() { return id(_a || (_a = __makeTemplateObject(["hello world"], ["hello world"]))); }
変数_a
に生成済みテンプレートオブジェクトをバインドして再利用しているのがわかる。
コンパイルエラーメッセージ・コマンドラインヘルプが多言語化
localeに合わせて各種言語ファイルが使用されるようになった。
// @ts-ignoreコメントでjsファイルのエラーを抑制できるようになった。
--allowJS
オプションを使ってJSファイルをロードした際に出るコンパイルエラーを、
if (false) { // @ts-ignore: Unreachable code error console.log("hello"); }
のような形で指定することで抑制できる。
--watchモードが高速化
--watch
機能をすべて書き直して高速化した。
プロジェクト全体をコンパイルするのではなく、変化したファイルのみを処理することで処理速度が向上した。
WriteOnlyな値をunusedとして処理するように
TypeScript2.6では、--noUnusedLocals
と--noUnusedParameters
オプションを刷新した。
値が宣言されているか書き込まれていても、その値が読み出されない限りunusedとしてマークされる。
function test(unused1: number) { unused1 = 0; } class Test { private unused2: number; constructor() { this.unused2 = 0; } }
上記のサンプルコードではunused1
とunused2
はともに書き込みはあるものの、
読み出しがないのでunusedとしてエラーになるので注意。
追記
LanguageService系の更新書くの忘れてた
implicit anyのQuick fixを追加
implicit anyが見つかった場合にnoImplicitAnyがtrueならQuickFixで推測した型を提案する。
JSDocをTypeScriptの型アノテーションに変換する
JSDocに書いた型注釈をTypeScriptの型に変換できるようになった。
呼び出しが必要なDecoratorにWarningを出すようになった
高階関数型の呼び出しが必要なDecoratorを呼び出し無しで使った場合に、
呼び出しを提案する。
@typesから自動でinstall
型定義がない場合に@typesから自動でインストールを提案する。
Ambient宣言内のdefault exportで式が使えなくなった
タイトルの通り
Intersection Typeの結果を変更
number & string, "foo" & 42,
のような不可能な型はnever型を返すように
lib.d.ts変更
Deprecation
getSymbolDisplayBuilder
APIが廃止になった。2.7で削除予定
基本的には代わりにTypeChecker#symbolToString
を使う。
もっと入り組んだユースケースの場合にはバージョン2.7でsymbolToString
を導入予定なのでそれを使う。
まとめ
今回はちょっと破壊的変更がいくつかあるので注意。
特に--strict
をONにしている人は総称型のアップキャストをしていないかをチェックした方がいい。