typescript 打字稿:铸造 HTMLElement
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12686927/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
TypeScript: casting HTMLElement
提问by Spongman
Does anyone know how to cast in TypeScript?
有谁知道如何在 TypeScript 中进行转换?
I'm trying to do this:
我正在尝试这样做:
var script:HTMLScriptElement = document.getElementsByName("script")[0];
alert(script.type);
but it's giving me an error:
但它给了我一个错误:
Cannot convert 'Node' to 'HTMLScriptElement': Type 'Node' is missing property 'defer' from type 'HTMLScriptElement'
(elementName: string) => NodeList
I can't access the 'type' member of the script element unless I cast it to the correct type, but I don't know how to do this. I searched the docs & samples, but I couldn't find anything.
除非我将其强制转换为正确的类型,否则我无法访问脚本元素的“类型”成员,但我不知道如何执行此操作。我搜索了文档和示例,但找不到任何内容。
回答by Spongman
TypeScript uses '<>' to surround casts, so the above becomes:
TypeScript 使用 '<>' 来包围强制转换,所以上面的代码变成了:
var script = <HTMLScriptElement>document.getElementsByName("script")[0];
However, unfortunately you cannot do:
但是,不幸的是你不能这样做:
var script = (<HTMLScriptElement[]>document.getElementsByName(id))[0];
You get the error
你得到错误
Cannot convert 'NodeList' to 'HTMLScriptElement[]'
But you can do :
但你可以这样做:
(<HTMLScriptElement[]><any>document.getElementsByName(id))[0];
回答by Fenton
As of TypeScript 0.9 the lib.d.ts
file uses specialized overload signatures that return the correct types for calls to getElementsByTagName
.
从 TypeScript 0.9 开始,该lib.d.ts
文件使用专门的重载签名,为调用getElementsByTagName
.
This means you no longer need to use type assertions to change the type:
这意味着您不再需要使用类型断言来更改类型:
// No type assertions needed
var script: HTMLScriptElement = document.getElementsByTagName('script')[0];
alert(script.type);
回答by Hyman128
You always can hack type system using:
您始终可以使用以下方法破解类型系统:
var script = (<HTMLScriptElement[]><any>document.getElementsByName(id))[0];
回答by Benoit B.
Do not type cast. Never. Use type guards:
不要类型转换。绝不。使用类型保护:
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.
Let the compiler do the work for you and get errors when your assumptions turn out wrong.
让编译器为您完成工作并在您的假设结果错误时出错。
It may look overkill in this case, but it will help you a lot if you come back later and change the selector, like adding a class that is missing in the dom, for example.
在这种情况下它可能看起来有点矫枉过正,但是如果您稍后回来更改选择器,例如添加一个在 dom 中缺少的类,它将对您有很大帮助。
回答by Johannes Fahrenkrug
To end up with:
最终得到:
- an actual
Array
object (not aNodeList
dressed up as anArray
) - a list that is guaranteed to only include
HTMLElements
, notNode
s force-casted toHTMLElement
s - a warm fuzzy feeling to do The Right Thing
- 一个实际的
Array
对象(不是NodeList
装扮成的Array
) - 保证只包含s的列表,而
HTMLElements
不是Node
s 强制转换为HTMLElement
s - 做正确的事的温暖模糊的感觉
Try this:
尝试这个:
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);
}
}
}
Enjoy.
享受。
回答by Leo
We could type our variable with an explicit return type:
我们可以使用显式返回类型键入变量:
const script: HTMLScriptElement = document.getElementsByName(id).item(0);
Or assert as(needed with TSX):
或断言为(需要TSX):
const script = document.getElementsByName(id).item(0) as HTMLScriptElement;
Or in simpler cases assert with angle-bracketsyntax.
或者在更简单的情况下使用尖括号语法断言。
A type assertion is like a type cast in other languages, but performs no special checking or restructuring of data. It has no runtime impact, and is used purely by the compiler.
类型断言类似于其他语言中的类型转换,但不执行特殊的数据检查或重组。它没有运行时影响,纯粹由编译器使用。
Documentation:
文档:
回答by Bill Ticehurst
Just to clarify, this is correct.
只是为了澄清,这是正确的。
Cannot convert 'NodeList' to 'HTMLScriptElement[]'
无法将“NodeList”转换为“HTMLScriptElement[]”
as a NodeList
is not an actual array (e.g. it doesn't contain .forEach
, .slice
, .push
, etc...).
作为NodeList
不是实际的阵列(例如它不包含.forEach
,.slice
,.push
,等等)。
Thus if it did convert to HTMLScriptElement[]
in the type system, you'd get no type errors if you tried to call Array.prototype
members on it at compile time, but it would fail at run time.
因此,如果它确实HTMLScriptElement[]
在类型系统中转换为,Array.prototype
那么在编译时尝试调用它的成员时不会出现类型错误,但在运行时会失败。
回答by Tobiasz Cudnik
This seems to solve the problem, using the [index: TYPE]
array access type, cheers.
这似乎解决了问题,使用[index: TYPE]
数组访问类型,欢呼。
interface ScriptNodeList extends NodeList {
[index: number]: HTMLScriptElement;
}
var script = ( <ScriptNodeList>document.getElementsByName('foo') )[0];
回答by Peter
Could be solved in the declaration file (lib.d.ts) if TypeScript would define HTMLCollection instead of NodeList as a return type.
如果 TypeScript 将 HTMLCollection 而不是 NodeList 定义为返回类型,则可以在声明文件 (lib.d.ts) 中解决。
DOM4 also specifies this as the correct return type, but older DOM specifications are less clear.
DOM4 也将此指定为正确的返回类型,但较旧的 DOM 规范不太清楚。
回答by Mike Keesey
Since it's a NodeList
, not an Array
, you shouldn't really be using brackets or casting to Array
. The property way to get the first node is:
由于它是NodeList
,而不是Array
,因此您不应该真正使用括号或强制转换为Array
。获取第一个节点的属性方式是:
document.getElementsByName(id).item(0)
You can just cast that:
你可以投射:
var script = <HTMLScriptElement> document.getElementsByName(id).item(0)
Or, extend NodeList
:
或者,扩展NodeList
:
interface HTMLScriptElementNodeList extends NodeList
{
item(index: number): HTMLScriptElement;
}
var scripts = <HTMLScriptElementNodeList> document.getElementsByName('script'),
script = scripts.item(0);