TypeScript: литье HTMLElement

Кто-нибудь знает, как привести в 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' элемента script, если не приведу его к правильному типу, но я не знаю, как это сделать. Я искал документы & образцы, но я не мог ничего найти.

Ответ 1

TypeScript использует '< > ' для окружающих отливок, поэтому выше:

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];

Ответ 2

Как и в TypeScript 0.9, файл lib.d.ts использует специализированные сигнатуры перегрузки, которые возвращают правильные типы для вызовов getElementsByTagName.

Это означает, что вам больше не нужно использовать утверждения типа для изменения типа:

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

Ответ 3

Вы всегда можете взломать систему типов, используя:

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

Ответ 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, например.

Ответ 5

В итоге:

  • фактический объект Array (а не NodeList, наряженный как Array)
  • список, который, как гарантируется, включает только HTMLElements, а не Node с принудительным нажатием на HTMLElement s
  • теплое нечеткое чувство, чтобы сделать The Right Thing

Попробуйте следующее:

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 really an Element
        if (node.nodeType == Node.ELEMENT_NODE) {
            elementList.push(node as HTMLElement);
        }
    }
}

Enjoy.

Ответ 6

Чтобы уточнить, это правильно.

Невозможно преобразовать 'NodeList' в 'HTMLScriptElement []'

как NodeList не является фактическим массивом (например, он не содержит .forEach, .slice, .push и т.д.).

Таким образом, если бы он преобразовывался в HTMLScriptElement[] в системе типов, вы не получали бы никаких ошибок типа, если бы вы пытались вызвать Array.prototype членов на нем во время компиляции, но это не сработало во время выполнения.

Ответ 8

Это, похоже, решает проблему, используя тип доступа к массиву [index: TYPE], приветствия.

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

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

Ответ 9

Может быть решено в файле декларации (lib.d.ts), если TypeScript будет определять HTMLCollection вместо NodeList как возвращаемый тип.

DOM4 также указывает это как правильный тип возврата, но более старые спецификации DOM менее ясны.

См. также http://typescript.codeplex.com/workitem/252

Ответ 10

Так как это a NodeList, а не Array, вы не должны использовать скобки или кастинг для Array. Свойство способ получить первый node:

document.getElementsByName(id).item(0)

Вы можете просто записать это:

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

Или растяните NodeList:

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

Ответ 11

Я бы также рекомендовал путеводители на сайтах

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 также позволяет вам указывать разные типы возврата, если точная строка предоставляется как аргумент функции. Например, TypeScript s эмбиентная декларация для метода createElement DOM выглядит следующим образом:

createElement(tagName: 'a'): HTMLAnchorElement;
createElement(tagName: 'abbr'): HTMLElement;
createElement(tagName: 'address'): HTMLElement;
createElement(tagName: 'area'): HTMLAreaElement;
// ... etc.
createElement(tagName: string): HTMLElement;

Это означает, что в TypeScript, когда вы звоните, например. document.createElement('video'), TypeScript знает, что возвращаемое значение HTMLVideoElement и сможет гарантировать, что вы взаимодействуете правильно с API-интерфейсом DOM без необходимости вводить assert.

Ответ 12

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