🎯

No overload matches this call… の解決方法

2023/07/01に公開

何が起きたのか?

以下のコードを書きました。

// index.tsx

window.addEventListener("keydown", handleKeyDown); <== @ココ!

function handleKeyDown(event: KeyboardEvent) {
      if (event.code === arrowKeys.left.keyCode) {
        // なにかのコード
      }
    }

”@ココ!” の行の、handleKeyDownに対して、TypeScript が次の問題を指摘しました。

No overload matches this call.
  Overload 1 of 2, '(type: "keydown", listener: (this: Window, ev: KeyboardEvent) => any, options?: boolean | AddEventListenerOptions | undefined): void', gave the following error.
    Argument of type '(event: KeyboardEvent<Element>) => void' is not assignable to parameter of type '(this: Window, ev: KeyboardEvent) => any'.
      Types of parameters 'event' and 'ev' are incompatible.
        Type 'KeyboardEvent' is missing the following properties from type 'KeyboardEvent<Element>': locale, nativeEvent, isDefaultPrevented, isPropagationStopped, persist
  Overload 2 of 2, '(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | undefined): void', gave the following error.
    Argument of type '(event: KeyboardEvent<Element>) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.
      Type '(event: KeyboardEvent<Element>) => void' is not assignable to type 'EventListener'.
        Types of parameters 'event' and 'evt' are incompatible.
          Type 'Event' is missing the following properties from type 'KeyboardEvent<Element>': altKey, charCode, ctrlKey, code, and 15 more.

ただ、実際の動作は問題なく、こちらが期待した通りでした。

しかし、問題ないとは言っても、いちいち指摘されると気になります。どこを直せばいいのでしょう?

エラーの解決方法

結論として、コードを以下のように書き換えました。

function handleKeyDown(event: KeyboardEvent) {

function handleKeyDown(event: globalThis.KeyboardEvent) {

event の型定義を厳密にしろということですね。

TypeScriptも納得してくれたみたいで、エラーは表示されなくなりました。

globalThisとは?

*GPT-3.5

The globalThis is a built-in global variable in JavaScript that provides a reference to the global object in any environment (including browsers and Node.js). It was introduced in ECMAScript 2020 to provide a consistent way of accessing the global object, regardless of the runtime environment.

globalThis は JavaScript の組み込みグローバル変数で、あらゆる環境(ブラウザや Node.js を含む)でグローバルオブジェクトへの参照を提供します。これは、実行環境に関係なくグローバルオブジェクトにアクセスする一貫した方法を提供するために ECMAScript 2020 で導入されました。

globalThisが必要なことにどのようにして気づいたか?

addEventListener 内で関数を直接書きます。

window.addEventListener("keypress",(e)=>{console.log(e.type)})

VSCodeであれば、eの部分にカーソルを合わせると、次のメッセージが現れるかと思います。

(parameter) e: globalThis.KeyboardEvent

画像だとこんなかんじ

これで必要な型がglobalThis.KeyboardEvent であることがわかります。

Discussion