why
TS に強くなりたかった
イベント系の型を知りたかった
参考
SmartHR 手を動かしながら学ぶ TypeScript
P.163 汎用的な処理を書いてみよう
CRA で React アプリ作成
npx create-react-app clstodo --template typescript
TS で作成
クラスベースに書き換えて start プロパティを追加
class App extends React.Component {
start() {
console.log('hello world');
}
render() {
return (
<div className="App">
</div>
);
}
}
クラスで書き換えて、
render プロパティの前に start プロパティを置く
これでブラウザで確認すると、start は動いていない。
load イベントを読み取って
window.addEventListener('load', () => {
const app = new App({})
app.start()
})
ブラウザのロードイベントを読み取って
App クラスを複製して app クラスを作り
複製された app の start プロパティを使う
すると console.log が動いた。
getElementById の型を追ってみる
const button = document.getElementById
('deleteAllDoneTask')
getElementById を深追いする。ctrl クリックをすると
lib.dom.d.ts に飛ぶ。
getElementById(elementId: string): HTMLElement | null;
引数の 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;
}
interface で Element や Document と EventElement ハンドラと GlobalEvent ハンドラ拡張して
その中におなじみの draggable, innerText, lang, などあり
クリックや add/remove EventListner もあり、ここで定義されていることがわかった。
これらは HTMLElementEventMap と言うものから拡張されている
HTMLElementEventMap
これを追ってみると
interface HTMLElementEventMap extends ElementEventMap, DocumentAndElementEventHandlersEventMap, GlobalEventHandlersEventMap {
}
- Element EventMap,
- Document and Element Event handler EventMap,
- Global Event Handler EventMap,
これらのイベントマップから拡張されている。
一つ一つ追ってみる。
ElementEventMap
interface ElementEventMap {
"fullscreenchange": Event;
"fullscreenerror": Event;
}
ElementEventMap は フルスクリーンの適用?とエラーのみがある
DocumentAndElementEventHandlersEventMap
interface DocumentAndElementEventHandlersEventMap {
"copy": ClipboardEvent;
"cut": ClipboardEvent;
"paste": ClipboardEvent;
}
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;
}
Global には
- キーボード系のイベント
- マウスが乗った時のイベント
- フォーム系のイベント
など HTML におけるほとんどのイベントがあることがわかった
これでHTMLElement の大枠が掴めた。
まとめ
クラスベースで TS をかくと、そのクラスのメソッドを使うときは、
新しく new でコピーを作ってコピーの同名メソッドを使う必要があり
HTMLEvent の型を掘っていくと GlobalEventHandlersEventMap
に行き着き、ここに殆どの HTML 要素でのイベントの型が入っていた。
Top comments (0)