こんにちは!TypeScriptの世界へようこそ。チーフアーキテクトの私です。
TypeScriptを書き始めると、「stringだのnumberだの」基本的な型には慣れてきますよね。でも、ちょっとコードが複雑になってくると、ふと現れる謎の存在……それが「`this`」です。
JavaScriptやTypeScriptの`this`って、なんだか神出鬼没で「今、お前は一体どこを指しているんだ!?」と頭を抱えた経験、ありませんか? 私は何度も夜のオフィスで画面に向かって叫びそうになりました(笑)。
今回は、そんな掴みどころのない`this`の型を、いとも簡単に見つけ出してくれるちょっとマニアックだけど実力派なユーティリティ型、`ThisParameterType
「難しそう……」なんて身構えなくて大丈夫ですよ。一歩ずつ、ゆっくり紐解いていきましょう!
—
そもそも `this` ってなに?(身近なたとえ話)
TypeScript(というかJavaScript)の`this`は、いわば「今、自分がどこに所属しているかを示す名札」のようなものです。
例えば、あなたが大きなおもちゃ箱の「ブロック係」だとします。あなたが「このブロックを取って!」と言うとき、その「この」が指すのは、あなたが今いる場所、すなわち「ブロック係のエリア」ですよね。
でも、もしあなたが「お人形係」のエリアに呼ばれて出張したとしたら、「この」が指す場所も変わります。JavaScriptの`this`は、関数が「どこから呼ばれたか」によってこの名札(中身)がコロコロ変わるので、型をつけるのが本当に大変なんです。
TypeScriptでは、関数の第一引数のところにこっそり `this: 型名` と書いて、「この関数を使うときは、この名札をつけてよね!」とあらかじめ約束させることができます。
—
主役登場:`ThisParameterType` ってどんな道具?
さて、今回学ぶ `ThisParameterType
お友達の関数を借りたときに、「この関数、使うときにどんな`this`(名札)を用意しなきゃいけないんだっけ?」と気になったとき、この子に聞けば一発で教えてくれます。
百聞は一見に如かず。実際にコードを見てみましょう。
基本的な使い方
まずは、`this`の型がちゃんと定義されている関数を用意します。
// お手伝いロボットの設定(イメージ)
// この関数は、thisとして「お掃除ロボット」の型を要求します
function cleanRoom(this: { location: string }, time: number) {
console.log(`${this.location} を ${time}分かけてお掃除します!`);
}
// さあ、ThisParameterType
// cleanRoom関数から「thisの型」だけを抜き出します
type CleanRoomThisType = ThisParameterType
// 抜き出した結果、CleanRoomThisType は以下のようになります:
// { location: string }
おぉ、すごい! `cleanRoom` という関数から、`this` の部分だけを綺麗にスポッと抜き出すことができました。
「え、これの何が便利なの?」って思いますよね。
実務では、他の人が作ったライブラリの関数を拡張したり、高度な関数型プログラミングで「関数の引数やthisをごっそり改造したい!」という時に、この型抽出力がもの凄く効いてくるんです。
—
つまずきやすいポイント:「thisがない関数」を渡したらどうなるの?
ここで、初心者の人がよくハマる罠をご紹介します。
「じゃあ、ふつうの関数に `ThisParameterType` を使ったらどうなるんだろう?」
気になりますよね。やってみましょう。
// 普通の関数(thisを指定していない)
function sayHello(name: string) {
console.log(`こんにちは、${name}さん!`);
}
// あれれ? thisを指定していない関数に使ってみると……?
type Result = ThisParameterType
さあ、この `Result` は一体どんな型になるでしょうか?
エラーになる? それとも `any` になる?
正解は……`unknown`(または `unknown` に近い挙動、正確には TypeScript の内部的な仕様で `unknown` や空のプレースホルダーのような扱い)になります。
> 💡 温かいアドバイス:
> 「あれ、思ってた型と違うのが出たぞ?」と思ったら、その関数がそもそも `this` の型を明示的に持っているか確認してみてください。「thisが定義されていない関数には、thisの型なんて存在しないから抽出できないよ」という、TypeScriptなりの優しさ(あるいは厳しさ)なんです。エラーで画面が真っ赤になっても、深呼吸して落ち着けば大丈夫ですよ!
—
実務でどう使う? ちょっとリアルな活用シーン
「型を抽出できるのはわかったけど、実務のどこで使うの?」
そんな疑問に、チーフアーキテクトとして現場の空気感をお伝えします。
例えば、コールバック関数を受け取るようなカスタムフックや、イベント処理のライブラリを書いているとします。その際、「渡された関数が、特定の `this` の文脈を要求しているかどうか」を判定し、型安全にラップ(包み直す)したい場合があります。
そんなときに、組み込みの型である OmitThisParameter とセットで使われることが多いです。
// 1. ユーザー情報を扱うthisの型
interface UserContext {
name: string;
}
// 2. thisとして UserContext を要求する関数
function greet(this: UserContext, message: string) {
console.log(`${this.name}さん、${message}`);
}
// 3. ThisParameterType で this の型を取り出す
type MyThis = ThisParameterType
// これを応用して、別の場所で型チェックに活かしたりします!
const user: MyThis = {
name: “田中さん”
};
// 実際にthisをバインドして実行
greet.call(user, “こんにちは!”);
このように、型と型をパズルのように組み合わせて、コード全体の安全性をガチガチに固めていくのがTypeScriptの醍醐味です。最初は呪文のように見えますが、一つひとつの部品の意味が分かると、コードを書くのがだんだん楽しくなってきますよ。
—
まとめ
お疲れ様でした! 今回は `ThisParameterType
- `ThisParameterType
` とは?
関数型から `this` の型だけを綺麗にスポッと抜き出す便利なユーティリティ型。
- どんなときに使う?
`this` を明示的に持つ関数の型を再利用したり、ライブラリなどの高度な型定義を読み解くとき。
- 注意するポイント
`this` が定義されていない関数に使うと、期待した型が取れない(あるいは `unknown` になる)ので、元の関数の定義を確認しよう。
TypeScriptの型パズルは、最初は難しく感じるかもしれませんが、あなたが書くコードの未来のバグを何個も防いでくれる心強い相棒です。分からないところがあれば、いつでもこの記事に戻ってきて、一つずつ確認してくださいね。
それでは、快適なTypeScriptライフを!チーフアーキテクトの私でした。

コメント