66293


TypeScript3.8.3 と Visual Studio Code 1.44.2 を利用しています。

* * *
[code]

    const div = document.createElement("div");
    div.onclick = (arg1) => {};
    
[/code]

としたとき、 `arg1` の型は `MouseEvent` と推論されました。

次に、 `div.onclick`
の定義を見てみると、[`lib.dom.d.ts`](https://github.com/microsoft/TypeScript/blob/v3.8.3/lib/lib.dom.d.ts#L5955)で次のように書かれていました

[code]

    onclick: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null;
    
[/code]

ので、引数を2つ採るのが正しいのかと思い、次のように書き直しました:

[code]

    const div = document.createElement("div");
    div.onclick = (arg1, arg2) => {};
    
[/code]

ところが、上のコードでは次のようなエラーになりました:

[code]

    error TS2322: Type '(arg1: any, arg2: any) => void' is not assignable to type '(this: GlobalEventHandlers, ev: MouseEvent) => any'.
    
[/code]

不思議に思い、いくつかのバリエーションを試したところ次の結果になりました:

[code]

    // OK
    // this の型は何でも良さそう
    // トランスパイル結果: const myfunc1 = (arg1) => { };
    const myfunc1: (this: string, arg: string) => any = (arg1) => {};
    
    // OK
    // 名前が this でなければ想定通り2つ引数を採る
    const myfunc2: (this_: string, arg: string) => any = (arg1, arg2) => {};
    
    // NG
    // https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Reserved_Words
    // this 以外のJavaScriptの予約語は引数名として利用できない？
    // (というか this はなぜ予約語なのに引数名として使える？)
    const myfunc3: (switch: string, arg: string) => any = (arg1) => {};
    
    // NG
    // this は第1引数でないと駄目らしい
    // error TS2680: A 'this' parameter must be the first parameter.
    const myfunc4: (arg: string, this: string) => any = (arg1, arg2) => {};
    
[/code]

上記結果より、引数名 `this` が特別扱いされているのだろうと予想しましたが、この挙動は実際にはどういう仕様に拠るものでしょうか。


CC BY-SA 4.0
2020-05-03T13:06:43.747
66249
2020-05-04T17:50:40.460
2808
question
javascript typescript
TypeScriptアロー関数型の引数名 this


> 上記結果より、引数名 this が特別扱いされているのだろうと予想しましたが、この挙動は実際にはどういう仕様に拠るものでしょうか。

TypeScriptのdocumentで `this parameters` と呼ばれてるものです。

<https://www.typescriptlang.org/docs/handbook/functions.html#this-parameters>

> this parameters are fake parameters that come first in the parameter list of
> a function:


CC BY-SA 4.0
2020-05-03T14:44:11.883
66254
2020-05-03T14:44:11.883
3068
66249
answer


関数が持つ `this` の型付けを行うための TypeScript 構文です。

_一般的には_ 、JavaScript において[関数内での this
の値は、関数の呼び出され方によって異なります](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/this#Function_context)。  
つまり、 _一般的には_ 関数の型宣言時に `this` を型付けすることはできません(`any`型として扱わざるを得ません)。

とはいえ、特定の呼び出され方しか想定する必要が無い関数もしばしば存在します。  
質問文にあるようなコールバック関数が典型的な例で、呼び出すのは既に実装済みのフレームワークのコードだけです。  
であれば`this`の型は実際には静的に定めることができます。  
こういった性質の関数に対してこの構文が利用可能です。

  * [Function `this` types · Issue #6018 · microsoft/TypeScript](https://github.com/microsoft/TypeScript/issues/6018)
    * simplicity versus purity 検討の結果、simplicity を優先して第 1 引数 `this` を特別扱いする仕様にした、みたいなことが書かれています(ちゃんと理解できてませんが)

* * *

質問ではアロー関数を用いていますが、[アロー関数自身は`this`を持たず](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this)、この構文で指定した
`this` (の型)は関数内に何も影響を及ぼしません。  
単に第 1 引数 `this` は無いものとして見なせば良いです。  
([`call()`の第1引数](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Invoked_through_call_or_apply)、として理解しておけば良いのかな、と思いました)


CC BY-SA 4.0
2020-05-04T17:50:40.460
66293
2020-05-04T17:50:40.460
2808
66249
answer