html 在typescript中设置Node.childNodes变量的类型

iih3973s  于 2023-04-27  发布在  TypeScript
关注(0)|答案(1)|浏览(180)

在我的代码中有:

const myElem: HTMLElement | null = document.getElementById("asd");
let arrow: any = [];

if (myElem) {
  arrow = myElem.childNodes;
  arrow[1].style.display = "none";
  arrow[2].style.display = "block";
}

我试图替换箭头变量的任何类型。它需要在获得值之前声明和初始化。我尝试:

let arrow: HTMLCollectionOf<HTMLElement> = [];

arrow = myElem.childNodes as HTMLCollectionOf<HTMLElement>;

因为官方文件说:NodeList objects are collections of nodes, usually returned by properties such as Node.childNodes and methods such as document.querySelectorAll().

The read-only childNodes property of the Node interface returns a live NodeList of child nodes of the given element where the first child node is assigned index 0. Child nodes include elements, text and comments.
nodelist doc
node childnode doc
我尝试的错误:
error TS2739: Type 'never[]' is missing the following properties from type 'HTMLCollectionOf<HTMLElement>': item, namedItem
error TS2352: Conversion of type 'NodeListOf<ChildNode>' to type 'HTMLCollectionOf<HTMLElement>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Property 'namedItem' is missing in type 'NodeListOf<ChildNode>' but required in type 'HTMLCollectionOf<HTMLElement>'.

ajsxfq5m

ajsxfq5m1#

如果你有一个特殊的原因要使用childNodes(比如想要非元素节点),将arrow的类型设置为NodeListOf<ChildNode>。所有的错误消息都在提示你该怎么做。就像他们在说“你说arrow是a,但是你给它赋了一个NodeListOf<ChildNode>类型的值,这不像a”。如果你走这条路,您还必须执行类型Assert/类型检查以使用style属性,因为该属性是在HTMLElement类型上,而不是在ChildNode类型上。
现在剩下的就是关于初始化的讨论了。
如果你不打算在if块的主体之后再次使用arrow,那么只需将arrow的作用域移动到if块内部。这样你甚至不需要编写类型注解。TypeScript会推断它。

const myElem = document.getElementById("asd");
if (myElem) {
  const arrow = myElem.childNodes;
  (arrow[1] as HTMLElement).style.display = "none";
  (arrow[2] as HTMLElement).style.display = "block";
}

如果你将在if块的主体之后再次使用arrow,那么你最好让类型反映它可能没有被if块初始化,以及你将它初始化为什么,我建议你使用null或者undefined来代替空数组,这样比较传统。除非你有一些很好的理由使用一个空数组作为“默认”值。无论你做什么,让类型工作。

const myElem = document.getElementById("asd");
let arrow: NodeListOf<ChildNode> | undefined = undefined;
if (myElem) {
  arrow = myElem.childNodes;
  (arrow[1] as HTMLElement).style.display = "none";
  (arrow[2] as HTMLElement).style.display = "block";
}

请注意,我去掉了手动输入的myElem,这是多余的,因为它与document.getElementById的返回类型相同。
如果你没有特别的理由使用childNodes(比如想要非元素节点),你也可以使用HTMLElement.children(),它返回一个HTMLCollection,但是你必须对HTMLElement进行类型Assert/类型检查,因为HTMLCollection的元素类型是Element而不是HTMLElement

相关问题