有谁知道如何在 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

我无法访问脚本元素的“type”成员,除非将其转换为正确的类型,但我不知道该怎么做。我搜索了文档和示例,但找不到任何内容。

有帮助吗?

解决方案

键字使用“<>”环绕声,因此以上变为:

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 文件使用专门的重载签名,为调用返回正确的类型 getElementsByTagName.

这意味着您不再需要使用类型断言来更改类型:

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

您始终可以使用:

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

不要键入铸造。绝不。使用类型警卫:

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中缺少的类。

To end up with:

  • an actual Array object (not a NodeList dressed up as an Array)
  • a list that is guaranteed to only include HTMLElements, not Nodes force-casted to HTMLElements
  • a warm fuzzy feeling to do The Right Thing

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.

Just to clarify, this is correct.

Cannot convert 'NodeList' to 'HTMLScriptElement[]'

as a NodeList is not an actual array (e.g. it doesn't contain .forEach, .slice, .push, etc...).

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.

Updated example:

const script: HTMLScriptElement = document.getElementsByName(id).item(0) as HTMLScriptElement;

Documentation:

TypeScript - Basic Types - Type assertions

This seems to solve the problem, using the [index: TYPE] array access type, cheers.

interface ScriptNodeList extends NodeList {
    [index: number]: HTMLScriptElement;
}

var script = ( <ScriptNodeList>document.getElementsByName('foo') )[0];

Could be solved in the declaration file (lib.d.ts) if TypeScript would define HTMLCollection instead of NodeList as a return type.

DOM4 also specifies this as the correct return type, but older DOM specifications are less clear.

See also http://typescript.codeplex.com/workitem/252

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:

document.getElementsByName(id).item(0)

You can just cast that:

var script = <HTMLScriptElement> document.getElementsByName(id).item(0)

Or, extend NodeList:

interface HTMLScriptElementNodeList extends NodeList
{
    item(index: number): HTMLScriptElement;
}
var scripts = <HTMLScriptElementNodeList> document.getElementsByName('script'),
    script = scripts.item(0);

I would also recommend the sitepen guides

https://www.sitepen.com/blog/2013/12/31/definitive-guide-to-typescript/ (see below) and 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:

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.

var script = (<HTMLScriptElement[]><any>document.getElementsByName(id))[0];    
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top