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
对象(不是一个装扮成Array
的NodeList
) - 一个保证只包含
HTMLElements
的列表,而不是强制转换成HTMLElement
的Node
- 一个温暖的模糊的感觉做正确的事情
尝试这个:
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规范不太清楚。
由于它是一个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。