TypeScript:强制转换HTMLElement

Spo*_*man 183 typescript

有谁知道如何使用TypeScript进行投射?

我正在尝试这样做:

var script:HTMLScriptElement = document.getElementsByName("script")[0];
alert(script.type);
Run Code Online (Sandbox Code Playgroud)

但它给了我一个错误:

Cannot convert 'Node' to 'HTMLScriptElement': Type 'Node' is missing property 'defer' from type 'HTMLScriptElement'
(elementName: string) => NodeList
Run Code Online (Sandbox Code Playgroud)

除非我将它转换为正确的类型,否则我无法访问脚本元素的'type'成员,但我不知道如何执行此操作.我搜索了文档和样本,但我找不到任何东西.

Spo*_*man 242

TypeScript使用'<>'来包围强制转换,因此上面变为:

var script = <HTMLScriptElement>document.getElementsByName("script")[0];
Run Code Online (Sandbox Code Playgroud)

但是,遗憾的是你做不到:

var script = (<HTMLScriptElement[]>document.getElementsByName(id))[0];
Run Code Online (Sandbox Code Playgroud)

你得到错误

Cannot convert 'NodeList' to 'HTMLScriptElement[]'
Run Code Online (Sandbox Code Playgroud)

但你可以这样做:

(<HTMLScriptElement[]><any>document.getElementsByName(id))[0];
Run Code Online (Sandbox Code Playgroud)

  • 在1.0之后,语法应该是```(<NodeListOf <HTMLScriptElement >> document.getElementsByName(id))[0];``` (3认同)
  • 您也可以使用 as 进行转换。var script = document.getElementsByName("script")[0] as HTMLScriptElement; (2认同)

Fen*_*ton 36

从TypeScript 0.9开始,该lib.d.ts文件使用专门的重载签名,返回正确的调用类型getElementsByTagName.

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

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

  • 这工作:name:(<HTMLInputElement> document.querySelector('#app-form [name]')).value, (3认同)

Jac*_*128 21

您始终可以使用以下方式破解类型系统:

var script = (<HTMLScriptElement[]><any>document.getElementsByName(id))[0];
Run Code Online (Sandbox Code Playgroud)


Ben*_* B. 18

不要输入演员表.决不.使用型号防护装置:

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.
Run Code Online (Sandbox Code Playgroud)

让编译器为您完成工作,并在您的假设错误时获取错误.

在这种情况下,它可能看起来有些过分,但如果你稍后再回来并改变选择器,它会帮助你很多,比如添加一个dom中缺少的类.

  • 这里看起来肯定很安全吧?我们可以保证 e 始终是 HTMLScriptElement 的实例,不是吗(我想,除非它不存在)? (2认同)

Cer*_*nce 14

一个更优雅的解决方案是使用泛型来指示您选择的元素的类型,而不是使用类型断言、类型保护或any解决该问题。

不幸的是,getElementsByName它不是通用的,但是querySelector并且querySelectorAll是。(querySelector而且querySelectorAll也更加灵活,因此在大多数情况下可能更可取。)

如果您将标签名称单独传递到querySelector或中querySelectorAll,则由于 中的以下行,它将自动正确键入lib.dom.d.ts

querySelector<K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;
Run Code Online (Sandbox Code Playgroud)

例如,要选择页面上的第一个脚本标记(如您的问题所示),您可以执行以下操作:

const script = document.querySelector('script')!;
Run Code Online (Sandbox Code Playgroud)

就是这样 - TypeScript 现在可以推断出现script在是一个HTMLScriptElement.

querySelector当您需要选择单个元素时使用。如果需要选择多个元素,请使用querySelectorAll。例如:

document.querySelectorAll('script')
Run Code Online (Sandbox Code Playgroud)

结果为NodeListOf<HTMLScriptElement>.

如果您需要更复杂的选择器,可以传递类型参数来指示要选择的元素的类型。例如:

const ageInput = document.querySelector<HTMLInputElement>('form input[name="age"]')!;
Run Code Online (Sandbox Code Playgroud)

结果被ageInput键入为HTMLInputElement.


Joh*_*rug 12

最终得到:

  • 一个实际的Array对象(不是NodeList打扮成一个Array)
  • 一个列表,保证只包括HTMLElements,而不是Node强制转换为HTMLElements
  • 一种温暖的模糊感做正确的事

试试这个:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请享用.


Bil*_*rst 9

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

无法将'NodeList'转换为'HTMLScriptElement []'

作为NodeList不是实际的阵列(例如它不包含.forEach,.slice,.push,等等).

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


Leo*_*Leo 5

更新的示例:

const script: HTMLScriptElement = document.getElementsByName(id).item(0) as HTMLScriptElement;
Run Code Online (Sandbox Code Playgroud)

说明文件:

TypeScript-基本类型-类型断言