TypeScript: casting HTMLElement
有人知道如何在TypeScript中进行转换吗?
我正在尝试这样做:
1 2 | var script:HTMLScriptElement = document.getElementsByName("script")[0]; alert(script.type); |
但这给了我一个错误:
1 2 | Cannot convert 'Node' to 'HTMLScriptElement': Type 'Node' is missing property 'defer' from type 'HTMLScriptElement' (elementName: string) => NodeList |
除非将其强制转换为正确的类型,否则我无法访问script元素的'type'成员,但我不知道该怎么做。 我搜索了文档和样本,但找不到任何东西。
TypeScript使用'<>'包围强制转换,因此以上内容变为:
1 | var script = <HTMLScriptElement>document.getElementsByName("script")[0]; |
但是,不幸的是,您不能执行以下操作:
1 | var script = (<HTMLScriptElement[]>document.getElementsByName(id))[0]; |
你得到错误
1 | Cannot convert 'NodeList' to 'HTMLScriptElement[]' |
但是你可以做:
1 | (<HTMLScriptElement[]>document.getElementsByName(id))[0]; |
从TypeScript 0.9开始,
这意味着您不再需要使用类型断言来更改类型:
1 2 3 | // No type assertions needed var script: HTMLScriptElement = document.getElementsByTagName('script')[0]; alert(script.type); |
您始终可以使用以下方法破解类型系统:
1 | var script = (<HTMLScriptElement[]>document.getElementsByName(id))[0]; |
不要键入强制类型转换。决不。使用防护罩:
1 2 3 4 | 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中缺少的类),它将对您有很大帮助。
最后以:
-
实际的
Array 对象(不是NodeList 打扮成Array 的对象) -
保证仅包含
HTMLElements 而不是强制广播到HTMLElement 的Node 的列表 - 做正确的事的温暖模糊的感觉
尝试这个:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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); } } } |
请享用。
只是为了澄清,这是正确的。
Cannot convert 'NodeList' to 'HTMLScriptElement[]'
因为
因此,如果确实在类型系统中将其转换为
更新的示例:
1 | const script: HTMLScriptElement = document.getElementsByName(id).item(0) as HTMLScriptElement; |
说明文件:
TypeScript-基本类型-类型断言
使用
1 2 3 4 5 | interface ScriptNodeList extends NodeList { [index: number]: HTMLScriptElement; } var script = ( <ScriptNodeList>document.getElementsByName('foo') )[0]; |
如果TypeScript将HTMLCollection而不是NodeList定义为返回类型,则可以在声明文件(lib.d.ts)中解决。
DOM4还将其指定为正确的返回类型,但是较旧的DOM规范尚不清楚。
另请参阅http://typescript.codeplex.com/workitem/252
1 | var script = (<HTMLScriptElement[]>document.getElementsByName(id))[0]; |
我还将推荐Sitepen指南
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 also allows you to specify different return types when an
exact string is provided as an argument to a function. For example,
TypeScript’s ambient declaration for the DOM’s createElement method
looks like this:
1 2 3 4 5 6 | createElement(tagName: 'a'): HTMLAnchorElement; createElement(tagName: 'abbr'): HTMLElement; createElement(tagName: 'address'): HTMLElement; createElement(tagName: 'area'): HTMLAreaElement; // ... etc. createElement(tagName: string): HTMLElement; |
This means, in TypeScript, when you call e.g.
document.createElement('video'), TypeScript knows the return value is
an HTMLVideoElement and will be able to ensure you are interacting
correctly with the DOM Video API without any need to type assert.
由于它是
1 | document.getElementsByName(id).item(0) |
您可以将其转换为:
1 | var script = <HTMLScriptElement> document.getElementsByName(id).item(0) |
或者,扩展
1 2 3 4 5 6 | interface HTMLScriptElementNodeList extends NodeList { item(index: number): HTMLScriptElement; } var scripts = <HTMLScriptElementNodeList> document.getElementsByName('script'), script = scripts.item(0); |