TypeScript:投射HTMLElement

任何人都知道如何投入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 

我不能访问脚本元素的“types”成员,除非我把它转换成正确的types,但我不知道该怎么做。 我搜查了文档和样本,但是找不到任何东西。

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]; 

从TypeScript 0.9开始, lib.d.ts文件使用专门的重载签名来返callback用getElementsByTagName的正确types。

这意味着你不再需要使用types断言来改变types:

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

你总是可以使用下面的黑客types系统:

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

只是为了澄清,这是正确的。

无法将“NodeList”转换为“HTMLScriptElement []”

因为NodeList不是一个实际的数组(例如它不包含.forEach.slice.push等等)。

因此,如果它在types系统中转换为HTMLScriptElement[] ,那么如果您在编译时尝试调用Array.prototype成员,则不会出现types错误,但在运行时会失败。

最终:

  • 一个实际的Array对象(不是一个装扮成ArrayNodeList
  • 一个保证只包含HTMLElements的列表,而不是强制转换成HTMLElementNode
  • 一个温暖的模糊的感觉做正确的事情

尝试这个:

 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); } } } 

请享用。

不要input。 决不。 使用types警卫:

 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. 

让编译器为你做这个工作,并在你的假设错误时得到错误。

在这种情况下,看起来可能有些过分,但是如果稍后再回来并更改select器,例如添加dom中缺less的类,它将对您有所帮助。

这似乎解决了问题,使用[index: TYPE]数组访问types,欢呼声。

 interface ScriptNodeList extends NodeList { [index: number]: HTMLScriptElement; } var script = ( <ScriptNodeList>document.getElementsByName('foo') )[0]; 

可以在声明文件(lib.d.ts)中解决,如果TypeScript将定义HTMLCollection而不是NodeList作为返回types。

DOM4也将其指定为正确的返回types,但较老的DOM规范不太清楚。

另见http://typescript.codeplex.com/workitem/252

由于它是一个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); 

我也会推荐sitepen指南

https://www.sitepen.com/blog/2013/12/31/definitive-guide-to-typescript/ (见下文)和https://www.sitepen.com/blog/2014/08/22/advanced -typescript的概念类types/

当一个精确的string作为参数提供给函数时,TypeScript还允许你指定不同的返回types。 例如,TypeScript的DOM的createElement方法的环境声明如下所示:

 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交互,而不需要inputassert。