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)

An Animated Guide to Node.js Event Loop

Node.js doesn’t stop from running other operations because of Libuv, a C++ library responsible for the event loop and asynchronously handling tasks such as network requests, DNS resolution, file system operations, data encryption, etc.

What happens under the hood when Node.js works on tasks such as database queries? We will explore it by following this piece of code step by step.