DEV Community

kaede
kaede

Posted on

手を動かしながら学ぶ TypeScript Part 4 -- クラスベースで作成し、HTMLElement の型定義を深掘りする 

why

TS に強くなりたかった
イベント系の型を知りたかった

参考

SmartHR 手を動かしながら学ぶ TypeScript

P.163 汎用的な処理を書いてみよう

CRA で React アプリ作成

npx create-react-app clstodo --template typescript
Enter fullscreen mode Exit fullscreen mode

TS で作成


クラスベースに書き換えて start プロパティを追加

class App extends React.Component {
  start() {
    console.log('hello world');
  }
  render() {
    return (
      <div className="App">
      </div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

クラスで書き換えて、
render プロパティの前に start プロパティを置く

これでブラウザで確認すると、start は動いていない。


load イベントを読み取って

window.addEventListener('load', () => {
  const app = new App({})
  app.start()
})
Enter fullscreen mode Exit fullscreen mode

ブラウザのロードイベントを読み取って
App クラスを複製して app クラスを作り
複製された app の start プロパティを使う
すると console.log が動いた。


getElementById の型を追ってみる

    const button = document.getElementById
('deleteAllDoneTask')
Enter fullscreen mode Exit fullscreen mode

getElementById を深追いする。ctrl クリックをすると

lib.dom.d.ts に飛ぶ。

    getElementById(elementId: string): HTMLElement | null;
Enter fullscreen mode Exit fullscreen mode

引数の elementId に文字列 を受け取り
戻り値として HTMLElement or null を返す

と言うことが読み取れる。


HTMLElement をさらに追ってみる

HTMLElement をさらに追ってみると

lib.dom.d.ts


/** Any HTML element. Some elements directly implement this interface, while others implement it via an interface that inherits it. */

interface HTMLElement extends Element, DocumentAndElementEventHandlers, ElementCSSInlineStyle, ElementContentEditable, GlobalEventHandlers, HTMLOrSVGElement {
    accessKey: string;
    readonly accessKeyLabel: string;
    autocapitalize: string;
    dir: string;
    draggable: boolean;
    hidden: boolean;
    innerText: string;
    lang: string;
//...

    click(): void;
    addEventListener
<K extends keyof HTMLElementEventMap>
(type: K, listener: 
(this: HTMLElement, ev: HTMLElementEventMap[K])
 => any, options?: boolean | AddEventListenerOptions):
 void;

    addEventListener
(type: string, listener: 
EventListenerOrEventListenerObject, options?: 
boolean | AddEventListenerOptions): void;

    removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;

    removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
Enter fullscreen mode Exit fullscreen mode

interface で Element や Document と EventElement ハンドラと GlobalEvent ハンドラ拡張して

その中におなじみの draggable, innerText, lang, などあり
クリックや add/remove EventListner もあり、ここで定義されていることがわかった。

これらは HTMLElementEventMap と言うものから拡張されている


HTMLElementEventMap

これを追ってみると

 

interface HTMLElementEventMap extends ElementEventMap, DocumentAndElementEventHandlersEventMap, GlobalEventHandlersEventMap {
}
Enter fullscreen mode Exit fullscreen mode
  • Element EventMap,
  • Document and Element Event handler EventMap,
  • Global Event Handler EventMap,

これらのイベントマップから拡張されている。

一つ一つ追ってみる。


ElementEventMap

interface ElementEventMap {
    "fullscreenchange": Event;
    "fullscreenerror": Event;
}
Enter fullscreen mode Exit fullscreen mode

ElementEventMap は フルスクリーンの適用?とエラーのみがある


DocumentAndElementEventHandlersEventMap

interface DocumentAndElementEventHandlersEventMap {
    "copy": ClipboardEvent;
    "cut": ClipboardEvent;
    "paste": ClipboardEvent;
}
Enter fullscreen mode Exit fullscreen mode

DocumentAndElementEventHandlerイベントマップには

copy, cut, paste のコピペイベントがある


GlobalEventHandlersEventMap

interface GlobalEventHandlersEventMap {
    "keydown": KeyboardEvent;
    "keypress": KeyboardEvent;
    "keyup": KeyboardEvent;
    "load": Event;

    "mouseleave": MouseEvent;
    "mousemove": MouseEvent;
    "mouseout": MouseEvent;
    "mouseover": MouseEvent;
    "mouseup": MouseEvent;
    "pause": Event;
    "play": Event;

    "select": Event;
    "selectionchange": Event;
    "selectstart": Event;
    "slotchange": Event;
    "stalled": Event;
    "submit": SubmitEvent;
}
Enter fullscreen mode Exit fullscreen mode

Global には

  • キーボード系のイベント
  • マウスが乗った時のイベント
  • フォーム系のイベント

など HTML におけるほとんどのイベントがあることがわかった

これでHTMLElement の大枠が掴めた。


まとめ

クラスベースで TS をかくと、そのクラスのメソッドを使うときは、
新しく new でコピーを作ってコピーの同名メソッドを使う必要があり

HTMLEvent の型を掘っていくと GlobalEventHandlersEventMap
に行き着き、ここに殆どの HTML 要素でのイベントの型が入っていた。

Top comments (0)