TypeScript:HTMLElementのキャスト


197

TypeScriptでキャストする方法を知っている人はいますか?

私はこれをやろうとしています:

var script:HTMLScriptElement = document.getElementsByName("script")[0];
alert(script.type);

しかし、それは私にエラーを与えています:

Cannot convert 'Node' to 'HTMLScriptElement': Type 'Node' is missing property 'defer' from type 'HTMLScriptElement'
(elementName: string) => NodeList

正しい型にキャストしない限り、script要素の 'type'メンバーにアクセスできませんが、これを行う方法がわかりません。ドキュメントとサンプルを検索しましたが、何も見つかりませんでした。


このキャストの問題は0.9では存在しないことに注意してください-以下の@Steveによる回答を参照してください。
グレッグガム

@GregGumスティーブからの回答が表示されない
スティーブシュラブ

回答:


255

TypeScriptは '<>'を使用してキャストを囲むため、上記は次のようになります。

var script = <HTMLScriptElement>document.getElementsByName("script")[0];

ただし、残念ながら次のことはできません。

var script = (<HTMLScriptElement[]>document.getElementsByName(id))[0];

エラーが発生します

Cannot convert 'NodeList' to 'HTMLScriptElement[]'

しかし、あなたはできる:

(<HTMLScriptElement[]><any>document.getElementsByName(id))[0];

$( '[type:input]')。each(function(index、element)を使用し、設定する必要のあるプロパティに応じてHTMLInputElementまたはHTMLSelectElementに要素をキャストする必要があると仮定します。 / get、キャストの使用(<HTMLSelectElement> <any> element).selectedIndex = 0;()要素の周りに()を追加します、一種の醜い
rekna


長い目で見ると(0.9がリリースされた後)、NodeList <HtmlScriptElement>などにキャストできるはずです。さらに、getElementsByNameは、文字列リテラルタイプのオーバーライドを使用して、まったくキャストせずにこれを正しく行うことができます。
Peter Burns

3
1.0以降、構文は次のようになります(<NodeListOf<HTMLScriptElement>>document.getElementsByName(id))[0];
Will Huang

1
キャストとして使用することもできます。var script = document.getElementsByName( "script")[0] as HTMLScriptElement;
JGFMK 2017

36

TypeScript 0.9以降、lib.d.tsファイルはへの呼び出しに対して正しい型を返す特別なオーバーロードシグネチャを使用しgetElementsByTagNameます。

つまり、型を変更するために型アサーションを使用する必要がなくなります。

// No type assertions needed
var script: HTMLScriptElement = document.getElementsByTagName('script')[0];
alert(script.type);

オブジェクト表記でそれをどのように行うのですか?つまり、{name:<HTMLInputElement>:document.querySelector( '#app-form [name]')。value、}を
Nikos

3
これは機能しました:name:(<HTMLInputElement> document.querySelector( '#app-form [name]'))。value、
Nikos

21

あなたはいつもタイプシステムをハックすることができます:

var script = (<HTMLScriptElement[]><any>document.getElementsByName(id))[0];

<any>を使用すると、型チェックをエスケープすることができますが、理想的ではありませんが、開発中はクールです
tit

21

キャストを入力しないでください。決して。タイプガードを使用する:

const e = document.getElementsByName("script")[0];
if (!(e instanceof HTMLScriptElement)) 
  throw new Error(`Expected e to be an HTMLScriptElement, was ${e && e.constructor && e.constructor.name || e}`);
// locally TypeScript now types e as an HTMLScriptElement, same as if you casted it.

コンパイラがあなたのために仕事をして、あなたの仮定が間違っていることが判明したときにエラーを受け取りましょう。

この場合はやり過ぎに見えるかもしれませんが、後で戻ってセレクターを変更すると、たとえばdomにないクラスを追加する場合などに役立ちます。


13

最終的に:

  • 実際のArrayオブジェクト(NodeListとしてドレスアップされていないArray
  • へのフォースキャストHTMLElementsではなく、のみが含まれることが保証されているリストNodeHTMLElement
  • 正しいことをするための暖かいファジー感

これを試して:

let nodeList : NodeList = document.getElementsByTagName('script');
let elementList : Array<HTMLElement> = [];

if (nodeList) {
    for (let i = 0; i < nodeList.length; i++) {
        let node : Node = nodeList[i];

        // Make sure it's really an Element
        if (node.nodeType == Node.ELEMENT_NODE) {
            elementList.push(node as HTMLElement);
        }
    }
}

楽しい。


10

明示的な戻り値の型で変数を入力できます。

const script: HTMLScriptElement = document.getElementsByName(id).item(0);

または次のようにアサートしますTSXで必要):

const script = document.getElementsByName(id).item(0) as HTMLScriptElement;

または、より単純なケースでは、角括弧構文でアサートします。


型アサーションは他の言語の型キャストに似ていますが、特別なチェックやデータの再構築は行いません。実行時への影響はなく、コンパイラーによってのみ使用されます。

ドキュメンテーション:

TypeScript-基本タイプ-タイプアサーション


9

明確にするために、これは正しいです。

「NodeList」を「HTMLScriptElement []」に変換できません

NodeList実際の配列ではありません(たとえば、それが含まれていない.forEach.slice.push...等、)。

したがってHTMLScriptElement[]、型システムで変換された場合Array.prototype、コンパイル時にメンバーを呼び出そうとしても型エラーは発生しませんが、実行時には失敗します。


1
確かにそれは正しいですが、完全に役立つわけではありません。別の方法としては、「型」を使用する方法があります。これは、有用な型チェックをまったく提供しません...
Spongman

3

これは問題を解決するようです、[index: TYPE]アレイアクセスタイプを使用して、乾杯。

interface ScriptNodeList extends NodeList {
    [index: number]: HTMLScriptElement;
}

var script = ( <ScriptNodeList>document.getElementsByName('foo') )[0];

1

TypeScriptが戻り値の型としてNodeListではなくHTMLCollectionを定義する場合、宣言ファイル(lib.d.ts)で解決できます。

DOM4もこれを正しい戻り値の型として指定していますが、古いDOM仕様はあまり明確ではありません。

http://typescript.codeplex.com/workitem/252も参照してください。


0

これはNodeListでなくなので、Arrayブラケットを使用したり、にキャストしたりしないでくださいArray。最初のノードを取得するプロパティの方法は次のとおりです。

document.getElementsByName(id).item(0)

あなたはそれをキャストすることができます:

var script = <HTMLScriptElement> document.getElementsByName(id).item(0)

または、拡張NodeList

interface HTMLScriptElementNodeList extends NodeList
{
    item(index: number): HTMLScriptElement;
}
var scripts = <HTMLScriptElementNodeList> document.getElementsByName('script'),
    script = scripts.item(0);

1
キャストUPDATEは、次のようになります。 const script = document.getElementsByName(id).item(0) as HTMLScriptElement;
マイクKeesey

つまり、TS 2.3では「このように見えます」。
マルケスラー2017年

0

私もサイトペンガイドをお勧めします

https://www.sitepen.com/blog/2013/12/31/definitive-guide-to-typescript/(下記参照)および https://www.sitepen.com/blog/2014/08/22/advanced -typescript-concepts-classes-types /

TypeScriptでは、正確な文字列が関数の引数として提供されている場合に、さまざまな戻り値の型を指定することもできます。たとえば、DOMのcreateElementメソッドに対するTypeScriptのアンビエント宣言は次のようになります。

createElement(tagName: 'a'): HTMLAnchorElement;
createElement(tagName: 'abbr'): HTMLElement;
createElement(tagName: 'address'): HTMLElement;
createElement(tagName: 'area'): HTMLAreaElement;
// ... etc.
createElement(tagName: string): HTMLElement;

つまり、TypeScriptでは、たとえばdocument.createElement( 'video')を呼び出すと、TypeScriptは戻り値がHTMLVideoElementであることを認識し、アサートを入力する必要なくDOM Video APIと正しく対話していることを確認できます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.