web-dev-qa-db-ja.com

Typescriptキーボードイベント:タイプ 'Event'の引数は、タイプ 'KeyboardEvent'のパラメーターに割り当てることができません

コードが完全に実行されても、次のエラーが発生します。

"TS2345: Argument of type 'Event' is not assignable to parameter of type 'KeyboardEvent'.
  Property 'altKey' is missing in type 'Event'." 

// In a Class

public listenTo = (window: Window) => {
  ['keydown', 'keyup'].forEach(eventName => {
     window.addEventListener(eventName, e => {
       this.handleEvent(e); // <- error here
     });
   });
}

public handleEvent = (event: KeyboardEvent) => {
    const { key } = event;
    //...
}

イベントタイプをKeyboardEventに定義しようとしましたが、次のエラーが発生しました:

 window.addEventListener(eventName, (e:KeyboardEvent) => {
           this.handleEvent(e); // <- error here
         });


 TS2345: Argument of type '(event: KeyboardEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.
  Type '(event: KeyboardEvent) => void' is not assignable to type 'EventListenerObject'.
 Property 'handleEvent' is missing in type '(event: KeyboardEvent) => void'.

問題を解決または解決する方法はありますか?

8
Fabrice

TypeScriptは、イベント名が文字列になることを知っているだけなので、ここでは完全に飛躍することができません。したがって、最も一般的なイベントタイプが使用されます。

以下の例は、スタンドアロンの実行例に変換された-だから私はデモのために「クラス外」のものを取りました...

文字列はkeydownおよびkeyupですが、型の安全性を保証し、コンパイラを無効にすることができます。

let listenTo = (window: Window) => {
  ['keydown', 'keyup'].forEach(eventName => {
     window.addEventListener(eventName, e => {
       handleEvent(<any>e);
     });
   });
}

let handleEvent = (event: KeyboardEvent) => {
    const { key } = event;
    //...
}

イベント名の配列に他の文字列が追加された場合、これは失敗します。

特殊なシグネチャにより、文字列を直接使用すると、完全な型安全性が利用可能になります。

  window.addEventListener('keydown', e => {
     handleEvent(e); // e is KeyboardEvent
  });

したがって、正しい型の良さを得るために、配列をより強く型付けることができます。

type KeyboardEventNames = 'keydown' | 'keyup';

let listenTo = (window: Window) => {
  const eventNames: KeyboardEventNames[] = ['keydown', 'keyup']; 
  eventNames.forEach(eventName => {
     window.addEventListener(eventName, e => {
       handleEvent(e);
     });
  });
}

let handleEvent = (event: KeyboardEvent) => {
    const { key } = event;
    //...
}

この最後の例では、配列内の要素のタイプをキーボードイベント名のみに制限しているため、コンパイラは古い文字列だけを処理していないことを認識し、イベントタイプを推測できます。

3
Fenton