要約
- jqueryで取得したmetaタグからcontentの値をts上で取得するには
-
(<HTMLMetaElement>$('meta[name="csrf-token"]')[0]).content
みたいにキャストすると良いよ
詳細
Railsからajax通信をする時、csrf-token
をheaderにつけて送ってあげることがままある。
その際にはmetaタグからcsrf-token
を取得していたが、typescriptへの移行に伴い次のエラーが出るようになった。むむ。
ERROR in ./commons/api.ts
[tsl] ERROR in /path/to/issus/issus/app/assets/javascripts/commons/api.ts(65,46)
TS2339: Property 'content' does not exist on type 'HTMLElement'.
該当箇所のコードがこちら
api.ts
export default class API {
// 中略
private static getRailsToken (): string {
return $('meta[name="csrf-token"]')[0].content // ← ココ
}
// 中略
}
どうやら $('meta[name="csrf-token"]')[0]
がHTMLElement
という型であり、そこにcontentというプロパティが無いらしい。
HTMLElement
のインターフェースを見てみると
lib.d.ts
interface HTMLElement extends Element {
accessKey: string;
readonly children: HTMLCollection;
contentEditable: string;
readonly dataset: DOMStringMap;
dir: string;
draggable: boolean;
hidden: boolean;
hideFocus: boolean;
innerText: string;
readonly isContentEditable: boolean;
lang: string;
readonly offsetHeight: number;
readonly offsetLeft: number;
readonly offsetParent: Element;
readonly offsetTop: number;
readonly offsetWidth: number;
onabort: (this: HTMLElement, ev: UIEvent) => any;
onactivate: (this: HTMLElement, ev: UIEvent) => any;
onbeforeactivate: (this: HTMLElement, ev: UIEvent) => any;
onbeforecopy: (this: HTMLElement, ev: ClipboardEvent) => any;
onbeforecut: (this: HTMLElement, ev: ClipboardEvent) => any;
onbeforedeactivate: (this: HTMLElement, ev: UIEvent) => any;
onbeforepaste: (this: HTMLElement, ev: ClipboardEvent) => any;
onblur: (this: HTMLElement, ev: FocusEvent) => any;
oncanplay: (this: HTMLElement, ev: Event) => any;
oncanplaythrough: (this: HTMLElement, ev: Event) => any;
onchange: (this: HTMLElement, ev: Event) => any;
onclick: (this: HTMLElement, ev: MouseEvent) => any;
oncontextmenu: (this: HTMLElement, ev: PointerEvent) => any;
oncopy: (this: HTMLElement, ev: ClipboardEvent) => any;
oncuechange: (this: HTMLElement, ev: Event) => any;
oncut: (this: HTMLElement, ev: ClipboardEvent) => any;
ondblclick: (this: HTMLElement, ev: MouseEvent) => any;
ondeactivate: (this: HTMLElement, ev: UIEvent) => any;
ondrag: (this: HTMLElement, ev: DragEvent) => any;
ondragend: (this: HTMLElement, ev: DragEvent) => any;
ondragenter: (this: HTMLElement, ev: DragEvent) => any;
ondragleave: (this: HTMLElement, ev: DragEvent) => any;
ondragover: (this: HTMLElement, ev: DragEvent) => any;
ondragstart: (this: HTMLElement, ev: DragEvent) => any;
ondrop: (this: HTMLElement, ev: DragEvent) => any;
ondurationchange: (this: HTMLElement, ev: Event) => any;
onemptied: (this: HTMLElement, ev: Event) => any;
onended: (this: HTMLElement, ev: MediaStreamErrorEvent) => any;
onerror: (this: HTMLElement, ev: ErrorEvent) => any;
onfocus: (this: HTMLElement, ev: FocusEvent) => any;
oninput: (this: HTMLElement, ev: Event) => any;
oninvalid: (this: HTMLElement, ev: Event) => any;
onkeydown: (this: HTMLElement, ev: KeyboardEvent) => any;
onkeypress: (this: HTMLElement, ev: KeyboardEvent) => any;
onkeyup: (this: HTMLElement, ev: KeyboardEvent) => any;
onload: (this: HTMLElement, ev: Event) => any;
onloadeddata: (this: HTMLElement, ev: Event) => any;
onloadedmetadata: (this: HTMLElement, ev: Event) => any;
onloadstart: (this: HTMLElement, ev: Event) => any;
onmousedown: (this: HTMLElement, ev: MouseEvent) => any;
onmouseenter: (this: HTMLElement, ev: MouseEvent) => any;
onmouseleave: (this: HTMLElement, ev: MouseEvent) => any;
onmousemove: (this: HTMLElement, ev: MouseEvent) => any;
onmouseout: (this: HTMLElement, ev: MouseEvent) => any;
onmouseover: (this: HTMLElement, ev: MouseEvent) => any;
onmouseup: (this: HTMLElement, ev: MouseEvent) => any;
onmousewheel: (this: HTMLElement, ev: WheelEvent) => any;
onmscontentzoom: (this: HTMLElement, ev: UIEvent) => any;
onmsmanipulationstatechanged: (this: HTMLElement, ev: MSManipulationEvent) => any;
onpaste: (this: HTMLElement, ev: ClipboardEvent) => any;
onpause: (this: HTMLElement, ev: Event) => any;
onplay: (this: HTMLElement, ev: Event) => any;
onplaying: (this: HTMLElement, ev: Event) => any;
onprogress: (this: HTMLElement, ev: ProgressEvent) => any;
onratechange: (this: HTMLElement, ev: Event) => any;
onreset: (this: HTMLElement, ev: Event) => any;
onscroll: (this: HTMLElement, ev: UIEvent) => any;
onseeked: (this: HTMLElement, ev: Event) => any;
onseeking: (this: HTMLElement, ev: Event) => any;
onselect: (this: HTMLElement, ev: UIEvent) => any;
onselectstart: (this: HTMLElement, ev: Event) => any;
onstalled: (this: HTMLElement, ev: Event) => any;
onsubmit: (this: HTMLElement, ev: Event) => any;
onsuspend: (this: HTMLElement, ev: Event) => any;
ontimeupdate: (this: HTMLElement, ev: Event) => any;
onvolumechange: (this: HTMLElement, ev: Event) => any;
onwaiting: (this: HTMLElement, ev: Event) => any;
outerText: string;
spellcheck: boolean;
readonly style: CSSStyleDeclaration;
tabIndex: number;
title: string;
blur(): void;
click(): void;
dragDrop(): boolean;
focus(): void;
msGetInputContext(): MSInputMethodContext;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
ほんとだ。たしかに無い。
そこで勘(エディタ補完)に頼って型キャストしてみると<HTMLMetaElement>
が見つかったので今度はそのインターフェースを覗いてみる。
lib.d.ts
interface HTMLMetaElement extends HTMLElement {
/**
* Sets or retrieves the character set used to encode the object.
*/
charset: string;
/**
* Gets or sets meta-information to associate with httpEquiv or name.
*/
content: string;
/**
* Gets or sets information used to bind the value of a content attribute of a meta element to an HTTP response header.
*/
httpEquiv: string;
/**
* Sets or retrieves the value specified in the content attribute of the meta object.
*/
name: string;
/**
* Sets or retrieves a scheme to be used in interpreting the value of a property specified for the object.
*/
scheme: string;
/**
* Sets or retrieves the URL property that will be loaded after the specified time has elapsed.
*/
url: string;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLMetaElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
無事content
を発見できた。ということで変更後のコードがこちら
api.ts
export default class API {
// 中略
private static getRailsToken (): string {
return (<HTMLMetaElement>$('meta[name="csrf-token"]')[0]).content
}
// 中略
}
無事tsc
も通過しめでたし。