我试着这样做:

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'成员,除非我将其转换为正确的类型,但我不知道如何做到这一点。我查了文件和样本,但什么都没找到。


当前回答

不要进行类型转换。从来没有。使用类型保护:

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中缺少的类,它将对您有很大帮助。

其他回答

你总是可以破解类型系统使用:

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中缺少的类,它将对您有很大帮助。

与其使用类型断言、类型保护或任何方法来解决这个问题,更优雅的解决方案是使用泛型来指示所选择的元素类型。

不幸的是,getElementsByName不是通用的,但是querySelector和querySelectorAll是通用的。(querySelector和querySelectorAll也要灵活得多,因此在大多数情况下可能更可取。)

如果你单独将一个标签名称传递给querySelector或querySelectorAll,它将自动正确地输入,因为下面这行在lib.dom.d.ts中:

querySelector<K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;

例如,要选择页面上的第一个脚本标签,如您的问题,您可以这样做:

const script = document.querySelector('script')!;

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

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

document.querySelectorAll('script')

结果类型为NodeListOf<HTMLScriptElement>。

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

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

导致ageInput被输入为HTMLInputElement。

这似乎解决了问题,使用[index: TYPE]数组访问类型,干杯。

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

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