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;
y
はany
になってしまっていた。
そのため、
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;
なぜなら、a
とb
がmap関数のパラメータf
を通して変換可能であると判断されていたため。
しかし2.4以降は実際のa
とb
の型を比較を行うため、このプログラムはコンパイルエラーとなる。
この変更は破壊的変更となるので注意
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
式をどう使うか。