概要
https://www.typescriptlang.org/tsconfig#noImplicitThis
{
"noImplicitThis": true
}
使われているthis
の型が暗黙的にany
になる場合にコンパイルエラーにします。
詳細
const func = function () {
console.log(this);
};
このコードは、下記のコンパイルエラーが出ます。
error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
function
による関数の場合、this
の値は宣言時に定まらないため、暗黙的に型は any
になるからです。
これを回避するためには 2 種類の方法があります。
1: アロー関数を使う。
アロー関数の場合、this
はそのアロー関数の定義コンテキストのthis
を参照するため、定義コンテキストでthis
が定まる場合で、かつそれが意図している参照なのであればアロー関数にするだけで OK です。
例えば、
const obj = {
count: 0,
hoge: function (label: string) {
return function () {
console.log(`${label}: ${this.count}`);
};
},
};
(実用性は何も考えないとして)上記のようにfunction
による関数をreturn
している場合、意図としてはobj.count
を参照したいが、function
ではbind
を使わないとthis
が定まりません。
(ちなみに、仮にこの返り値の関数をbind(this)
してからreturn
してもエラーは消えません)
こういう場合はアロー関数にするだけで OK。
const obj = {
count: 0,
hoge: function (label: string) {
return () => {
console.log(`${label}: ${this.count}`);
};
},
};
2: 明示的にthis
の型を指定する。
TypeScript では、function
による関数宣言で作られる関数の第一引数の名前がthis
の場合、その引数の型は関数内のthis
の型を指します。
(アロー関数にはこの機能は存在しません: 'An arrow function cannot have a 'this' parameter.ts(2730)'
)
そしてその場合、2 個目以降の引数が実際のその関数の引数になります。
例えば下記のような、this
をconsole.log
する関数があったとして、
const logThis = function () {
console.log(this);
};
これは
error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
が出るのでコンパイル出来ません。
しかし、この関数はアロー関数に変えても別のエラーが出ます。
error TS7041: The containing arrow function captures the global value of 'this'.
そこで、
const logThis = function (this: object) {
console.log(this);
};
このように引数で this を指定すると、console.log(this);
部分のthis
は型が定まります(この場合はobject
)。
この書き方をした場合は、2 個目以降の引数が実際の関数の引数になるため、呼び出しは引数を何も取らない形で実行できます。
const logThis = function (this: object) {
console.log(`this`);
};
const obj = { logThis };
obj.logThis();
引数が欲しい場合はこう。
const logThis = function (this: object, label: string) {
console.log(`${label}: ${this}`);
};
const obj = { logThis };
obj.logThis("HOGEHOGE:");
出力される js を見れば通常の関数として扱われているのがわかります。
var logThis = function (label) {
console.log(label + ": " + this);
};
var obj = { logThis: logThis };
obj.logThis("HOGEHOGE");