JavaScriptでは、thisの型が変わることがあります。
class Sample {
hello() { console.log(this.constructor.toString()); }
}
const sample = new Sample();
sample.hello(); //(1) => function Sample() {}
let hello = sample.hello;
hello(); //(2) => function Object() { [native code] }
(1)ではthisはSample型でしたが、(2)ではObject型になりました。
関数の使い方を誤ってthisが想定外の型になり、思わぬエラーになることがあります。
TypeScriptでは、関数の1番目の引数をthisにすることで、thisの型を指定できます。
class Sample {
hello(this: Sample) { console.log(this.constructor.toString()); }
}
thisは仮の引数であり、実際には存在しません。
関数を呼び出すときは、引数thisを指定する必要はありません。
先ほどのコードをコンパイルすると(2)のところで、コンパイルエラーになります。
const sample = new Sample();
sample.hello();
let hello = sample.hello;
hello(); //(2) error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'Sample'.
コンパイラに「–noImplicitThis」オプションを渡すと、関数内でthisの型を指定せずにthisを使うとエラーになります。
class Sample {
name: string = "hello";
}
function hello() { console.log(this.name); }
hello.bind(new Sample())(); //=> error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
JavaScriptではthisにまつわるトラブルが起こりがちです。
TypeScriptで「–noImplicitThis」をつけてthisの型を忘れずに指定すれば、安全なプログラミングができそうです。