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

this引数 (this parameter)

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

ts
class Male {
private name: string;
 
public constructor(name: string) {
this.name = name;
}
 
public toString(): string {
return `Monsieur ${this.name}`;
}
}
 
class Female {
private name: string;
 
public constructor(name: string) {
this.name = name;
}
 
public toString(this: Female): string {
return `Madame ${this.name}`;
}
}
ts
class Male {
private name: string;
 
public constructor(name: string) {
this.name = name;
}
 
public toString(): string {
return `Monsieur ${this.name}`;
}
}
 
class Female {
private name: string;
 
public constructor(name: string) {
this.name = name;
}
 
public toString(this: Female): string {
return `Madame ${this.name}`;
}
}

上記クラスMaleFemaleはほぼ同じ構造ですがtoString()のメソッドの引数が異なります。

MaleFemaleはともに普通の用途で使うことができます。

ts
const male: Male = new Male("Frédéric");
const female: Female = new Female("Frédérique");
 
male.toString();
Monsieur Frédéric
female.toString();
Madame Frédérique
ts
const male: Male = new Male("Frédéric");
const female: Female = new Female("Frédérique");
 
male.toString();
Monsieur Frédéric
female.toString();
Madame Frédérique

ですが各インスタンスのtoString()を変数に代入すると意味が変わります。

ts
const maleToStr: () => string = male.toString;
const femaleToStr: (this: Female) => string = female.toString;
 
maleToStr();
femaleToStr();
The 'this' context of type 'void' is not assignable to method's 'this' of type 'Female'.2684The 'this' context of type 'void' is not assignable to method's 'this' of type 'Female'.
ts
const maleToStr: () => string = male.toString;
const femaleToStr: (this: Female) => string = female.toString;
 
maleToStr();
femaleToStr();
The 'this' context of type 'void' is not assignable to method's 'this' of type 'Female'.2684The 'this' context of type 'void' is not assignable to method's 'this' of type 'Female'.

femaleToStr()のコンテキストがFemaleではないとの指摘を受けています。このコードを実行することはできません。ちなみにこの対応をしていないmaleToStr()は実行こそできますが実行時に例外が発生します。

js
class Male {
// ...
toString() {
return `Monsieur ${this.name}`;
TypeError: Cannot read property 'name' of undefined
}
}
js
class Male {
// ...
toString() {
return `Monsieur ${this.name}`;
TypeError: Cannot read property 'name' of undefined
}
}

引数のthisを指定することによって意図しないメソッドの持ち出しを避けることができます。