abcdefGets

ゲッツ!

typescript 2.4 の新機能

typescript2.4がでたので新機能を確認。

Dynamic Import Expressionsのサポート

import('...')式がサポートされた。

import式を使うことで多くのバンドラーがコード分割をすることが可能になるので、
module: esnextで出力するのがおすすめだそう。

async function getZipFile(name: string, files: File[]): Promise<File> {
  const zipUtil = await import('./utils/create-zip-file');
  const zipContents = await zipUtil.getContentAsBlob(files);
  return new File(zipContents, name);
}

String Enumsのサポート

待望?の文字列enumがサポートされた。

enum Colors {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE",
}

ただし制限として、数値enumの際に可能だった、メンバプロパティからプロパティ名の取得はできない。

Colors[Colors.Red] // これはできない。

interfaceのgeneric型のサポートを強化

戻り値の推論能力の強化

戻り値から型パラメータを導出できるようになった。

function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[] {
  return a => a.map(f);
}

const lengths: (a: string[]) => number[] = arrayMap(s => s.length);

Promiseもこのようにエラーとすることができるように。

let x: Promise<string> = new Promise(resolve => {
  resolve(10);
  //      ~~ Error!
});

文脈からの型パラメータの導出

いかのような定義があった場合

let f: <T>(x: T) => T = y => y;

yanyになってしまっていた。
そのため、

let f: <T>(x: T) => T = y => y() + y.foo.bar;

のような式は型チェックをスルーしてしまっていたが、
2.4からyが正しく導出され、エラーとなるようになった。

generic関数の方チェックを厳格化

以下のような関数があった場合、

type A = <T, U>(x: T, y: U) => [T, U];
type B = <S>(x: S, y: S) => [S, S];

function f(a: A, b: B) {
  a = b;  // Error
  b = a;  // Ok
}

AがBと互換性があるかをチェックできるようになり、互換性があれば、代入も可能になった。

コールバック関数の方の反変性チェックを厳格化

2.4以前のバージョンでは以下のプログラムではエラーが起きなかった。

interface Mappable<T> {
  map<U>(f: (x: T) => U): Mappable<U>;
}

declare let a: Mappable<number>;
declare let b: Mappable<string | number>;

a = b;
b = a;

なぜなら、abがmap関数のパラメータfを通して変換可能であると判断されていたため。
しかし2.4以降は実際のabの型を比較を行うため、このプログラムはコンパイルエラーとなる。
この変更は破壊的変更となるので注意

Weak Typesの導入

以下のように、すべてがoptionalな型をWeakTypeとして区別することになった。

interface Options {
  data?: string,
  timeout?: number,
  maxRetries?: number,
}

2.4からはこのWeakTypeに対しても、存在しないプロパティを持つ型を代入するとエラーになる。

function sendMessage(options: Options) {
  // ...
}

const opts = {
  payload: "hello world!",
  retryOnFail: true,
}

// Error!
sendMessage(opts);
// optsとOptions型で一致するプロパティがないためエラー

この変更は破壊的変更となるので注意

現在以下のWorkaroundが提案されている。

  • 実際にプロパティが存在する場合のみ宣言する。
  • WeakTypeには{[propName: string]: {}}のようなインデックス型を定義する。
  • opts as Optionsのように型アサーションを使って変換する。

まとめ

型チェックの強化がメインの変更点になった。
破壊的変更が幾つかありますが、WeakTypeのとこはちょっと注意した方が良さそう。
あとはimport式をどう使うか。