整理したものはTech sheetsにあるよ

2016年12月12日月曜日

TypeScript 2.1.4でXMLHttpRequestのコールバックがコンパイルエラー

みんなー!

TypeScriptで、次のコードをコンパイルしてみよう!


var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://tech.mokelab.com', true);
xhr.onload = function() {
    console.log(this.response);
};
xhr.send();

onloadプロパティにセットするコールバック関数は、呼ばれる時、thisにXMLHttpRequestがセットされる。だから、アローではなくfunctionを使うんだったね!

でもこのコード、TypeScript 2.1.4でコンパイルすると次のようなエラーがでちゃう。


moke.ts(4,22): error TS2339: Property 'response' does not exist on type 'XMLHttpRequestEventTarget'.

responseっていうプロパティはXMLHttpRequestにあるはずなんだけど、なぜか型がXMLHttpRequestEventTargetになってて、「そんなプロパティは知らないよ」というコンパイルエラーが出てるね。

この動きを理解するために、TypeScript 2で導入された構文を確認しよう!TypeScript 2で、コールバック関数をセットするプロパティに、thisの型が指定できるようになったんだ。こんな感じで定義を書くよ。


interface Moke {
    onclick: (this: MyObject, ev: Event) => any;
}

第一引数名がthisで、型を「実際に呼ばれる時にthisにセットされている型」にすると、function()の中でも適切に型チェックしてくれる!

そして本題のXMLHttpRequestのコールバック部分。2.1.3までは次のようになっているよ(一部のみ抜粋)。

interface XMLHttpRequestEventTarget {
    // onloadのみ掲載
    onload: (this: this, ev: Event) => any;
}

これが、TypeScript 2.1.4だとこうなってた!

interface XMLHttpRequestEventTarget {
    // onloadのみ掲載
    onload: (this: XMLHttpRequestEventTarget, ev: Event) => any;
}

もちろん実際に呼ばれるときは、XMLHttpRequestEventTargetを実装しているXMLHttpRequestがthisにセットされるよ。 なので、いまひとつだけど次のようにキャストするしかないみたい。。。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://tech.mokelab.com', true);
xhr.onload = function() {
    console.log((<XMLHttpRequest>this).response);
};
xhr.send();

同じ問題でハマった人の助けになるといいなー