メインコンテンツまでスキップ

noImplicitThis

noImplicitThisはthisの型注釈を必須にするコンパイラオプションです。

  • デフォルト: strictが有効の場合はtrue、それ以外はfalse
  • 追加されたバージョン: 2.0
  • TypeScript公式が有効化推奨

解説

名前付き関数、匿名関数はアロー関数と異なり、実行時にthisが決定されます。そのため、内部でthisを使っているとそれらは関数を書いている時点ではany型と同じ扱いになります。

たとえば、対角線の長さを求める関数lengthOfDiagonal()を考えます。(横, 縦)を (width, height) とすれば関数は次のようになります。

ts
function lengthOfDiagonal(): number {
return (this.width ** 2 + this.height ** 2) ** (1 / 2);
}
ts
function lengthOfDiagonal(): number {
return (this.width ** 2 + this.height ** 2) ** (1 / 2);
}

これをwidth, heightをプロパティに持つオブジェクトのインスタンスに代入すれば対角線の長さを計算できます。

ts
const area = {
width: 3,
height: 4,
diagonal: lengthOfDiagonal,
};
 
console.log(area.diagonal());
5
ts
const area = {
width: 3,
height: 4,
diagonal: lengthOfDiagonal,
};
 
console.log(area.diagonal());
5

このとき、打ち間違いでwidthwitchとしてしまったとするとこの関数は意図した結果を返さなくなります。

ts
const area = {
witch: 3,
height: 4,
diagonal: lengthOfDiagonal,
};
 
console.log(area.diagonal());
NaN
ts
const area = {
witch: 3,
height: 4,
diagonal: lengthOfDiagonal,
};
 
console.log(area.diagonal());
NaN

このオプションを有効にするとany型として認識されてしまっているthisがどの型であるかを明確にできない限り実行することができなくなります。

ts
function lengthOfDiagonal(): number {
return (this.width ** 2 + this.height ** 2) ** (1 / 2);
'this' implicitly has type 'any' because it does not have a type annotation.
'this' implicitly has type 'any' because it does not have a type annotation.
2683
2683
'this' implicitly has type 'any' because it does not have a type annotation.
'this' implicitly has type 'any' because it does not have a type annotation.
}
ts
function lengthOfDiagonal(): number {
return (this.width ** 2 + this.height ** 2) ** (1 / 2);
'this' implicitly has type 'any' because it does not have a type annotation.
'this' implicitly has type 'any' because it does not have a type annotation.
2683
2683
'this' implicitly has type 'any' because it does not have a type annotation.
'this' implicitly has type 'any' because it does not have a type annotation.
}

これを回避するためにはthisが何かを明示します。引数のthisについては関数のページに詳細がありますので併せてご参照ください。

📄️ this引数

アロー関数以外の関数とクラスのメソッドの第1引数はthisという特殊な引数を受けることができます。これは使用するコンテキストによってthisの意味するところが変わってしまうため、これらがどのコンテキストで使用されるべきなのかをTypeScriptに伝えるために使います。このthisは呼び出す側は意識する必要はありません。第2引数以降を指定してください。

ts
type Area = {
width: number;
height: number;
diagonal(): number;
};
 
function lengthOfDiagonal(this: Area): number {
return (this.width ** 2 + this.height ** 2) ** (1 / 2);
}
 
const area: Area = {
width: 3,
height: 4,
diagonal: lengthOfDiagonal,
};
ts
type Area = {
width: number;
height: number;
diagonal(): number;
};
 
function lengthOfDiagonal(this: Area): number {
return (this.width ** 2 + this.height ** 2) ** (1 / 2);
}
 
const area: Area = {
width: 3,
height: 4,
diagonal: lengthOfDiagonal,
};