abcdefGets

ゲッツ!

TypeScript 2.6 変更点と注意点

TypeScript2.6が出たので変更点を記載
RCからほぼ変更点がない。

Strict Function Typeフラグの導入

--strictFunctionTypesというフラグが導入される。
このフラグは--strictフラグに内包されており、--strictの場合は自動でONになるが、
--strictFunctionTypesfalseにすることで個別にOFFにすることもできる。

動作

関数の引数に対するVarianceの動作を変更する。
TypeScriptの関数のVarianceについては以前下のスライドで説明したので参照。

speakerdeck.com

今回の--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を受け取る関数を渡すと、DogAnimalの派生型である限り、
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;
  }
}

上記のサンプルコードではunused1unused2はともに書き込みはあるものの、
読み出しがないので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

getSymbolDisplayBuilderAPIが廃止になった。2.7で削除予定
基本的には代わりにTypeChecker#symbolToStringを使う。
もっと入り組んだユースケースの場合にはバージョン2.7でsymbolToStringを導入予定なのでそれを使う。

まとめ

今回はちょっと破壊的変更がいくつかあるので注意。
特に--strictをONにしている人は総称型のアップキャストをしていないかをチェックした方がいい。