Tapescript: casting HTMLElement
quelqu'un sait jouer à la typographie?
je suis en train de le faire:
var script:HTMLScriptElement = document.getElementsByName("script")[0];
alert(script.type);
mais il me donne une erreur:
Cannot convert 'Node' to 'HTMLScriptElement': Type 'Node' is missing property 'defer' from type 'HTMLScriptElement'
(elementName: string) => NodeList
Je ne peux pas accéder au membre 'type' de l'élément script à moins de le lancer au bon type, mais je ne sais pas comment faire. j'ai cherché dans les docs & samples, mais je n'ai rien trouvé.
12 réponses
dactylographié utilise '<>' pour entourer des moulages, de sorte que ce qui précède devient:
var script = <HTMLScriptElement>document.getElementsByName("script")[0];
malheureusement, vous ne pouvez pas faire:
var script = (<HTMLScriptElement[]>document.getElementsByName(id))[0];
vous obtenez l'erreur
Cannot convert 'NodeList' to 'HTMLScriptElement[]'
mais vous pouvez faire:
(<HTMLScriptElement[]><any>document.getElementsByName(id))[0];
à partir de la version dactylographiée 0.9 le fichier lib.d.ts
utilise des signatures de surcharge spécialisées qui renvoient les bons types d'appels à getElementsByTagName
.
cela signifie que vous n'avez plus besoin d'utiliser les assertions de type pour changer le type:
// No type assertions needed
var script: HTMLScriptElement = document.getElementsByTagName('script')[0];
alert(script.type);
vous pouvez toujours hacker le système de type en utilisant:
var script = (<HTMLScriptElement[]><any>document.getElementsByName(id))[0];
À la fin:
- réelle
Array
objet (pas unNodeList
habillé comme unArray
) - une liste qui est garantie pour inclure seulement
HTMLElements
, pasNode
s force-moulé àHTMLElement
s - une ambiance chaleureuse et douillette de faire La bonne Chose
Essayez ce qui suit:
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);
}
}
}
de Profiter de.
Juste pour clarifier, c'est correct.
ne peut pas convertir "NodeList" en "HTMLScriptElement []
comme NodeList
n'est pas un tableau réel (par exemple, il ne contient pas .forEach
, .slice
, .push
, etc...).
ainsi si elle convertissait en HTMLScriptElement[]
dans le système de type, vous n'obtiendriez pas d'erreurs de type si vous essayiez d'appeler des membres Array.prototype
sur elle au moment de la compilation, mais il serait l'échec au moment de l'exécution.
ne pas taper cast. Jamais. Utiliser le type de garde:
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.
Laisser le compilateur faire le travail pour vous et obtenez des erreurs lors de vos hypothèses trompez.
cela peut sembler exagéré dans ce cas, mais cela vous aidera beaucoup si vous revenez plus tard et changez le sélecteur, comme ajouter une classe qui manque dans le dom, par exemple.
cela semble résoudre le problème, en utilisant le type d'accès [index: TYPE]
tableau, santé.
interface ScriptNodeList extends NodeList {
[index: number]: HTMLScriptElement;
}
var script = ( <ScriptNodeList>document.getElementsByName('foo') )[0];
pourrait être résolu dans le dossier de déclaration (lib.D. ts) si TypeScript définirait HTMLCollection au lieu de NodeList comme un type de retour.
DOM4 spécifie également que C'est le bon type de retour, mais les anciennes spécifications DOM sont moins claires.
Voir aussi http://typescript.codeplex.com/workitem/252
Puisqu'il s'agit d'un NodeList
, pas d'un Array
, vous ne devriez pas vraiment utiliser de crochets ou de casting à Array
. La façon de propriété pour obtenir le premier noeud est:
document.getElementsByName(id).item(0)
vous pouvez juste lancer que:
var script = <HTMLScriptElement> document.getElementsByName(id).item(0)
Ou, étendre NodeList
:
interface HTMLScriptElementNodeList extends NodeList
{
item(index: number): HTMLScriptElement;
}
var scripts = <HTMLScriptElementNodeList> document.getElementsByName('script'),
script = scripts.item(0);
je recommande également les guides de sitepen
https://www.sitepen.com/blog/2013/12/31/definitive-guide-to-typescript (voir ci-dessous) et https://www.sitepen.com/blog/2014/08/22/advanced-typescript-concepts-classes-types /
dactylographié vous permet également de spécifier différents types de retour quand un exact chaîne est fournie comme argument d'une fonction. Exemple, Déclaration d'ambient de TypeScript pour la méthode createElement de DOM on dirait:
createElement(tagName: 'a'): HTMLAnchorElement;
createElement(tagName: 'abbr'): HTMLElement;
createElement(tagName: 'address'): HTMLElement;
createElement(tagName: 'area'): HTMLAreaElement;
// ... etc.
createElement(tagName: string): HTMLElement;
cela signifie, à la typographie, lorsque vous appelez par exemple document.createElement ('video'), Tapescript sait que la valeur de retour est un HTMLVideoElement et sera en mesure de s'assurer que vous êtes en interaction correctement avec L'API vidéo DOM sans besoin de taper assert.
var script = (<HTMLScriptElement[]><any>document.getElementsByName(id))[0];
exemple mis à jour:
const script: HTMLScriptElement = document.getElementsByName(id).item(0) as HTMLScriptElement;
de la Documentation: