JavaScript 类型注解

use*_*987 4 javascript types webstorm

我正在使用 WebStorm 并遇到以下问题:

/** @type {HTMLCanvasElement} */
var buffered_canvas = document.createElement("canvas");
buffered_canvas.width = 256;
buffered_canvas.height = 256;
Run Code Online (Sandbox Code Playgroud)

当我将 buffered_canvas 注释为 HTMLCanvasElement 类型时,它会抱怨 createElement 返回一个无法分配给 HTMLCanvasElement 的 HTMLElement。

/** @type {HTMLElement} */
var buffered_canvas = document.createElement("canvas");
buffered_canvas.width = 256;
buffered_canvas.height = 256;
Run Code Online (Sandbox Code Playgroud)

当我将其更改为 HTMLElement 类型时,它会抱怨 HTMLElement 上未定义宽度和高度属性。

我该如何正确执行此操作?

另外——我是 JavaScript 的新手,无法找到任何真正的规范,例如 HTMLElement 及其具有的属性或 createCanvas 的方法签名以及它返回的类型。有时我会在 MDN 上找到不错的东西,但它们通常不包含方法签名或很多类型信息。这个东西有什么好的资源吗?

谢谢

Dag*_*bit 5

你可以像这样输入强制转换:

var buffered_canvas = /** @type {HTMLCanvasElement} */ (document.createElement("canvas"));
Run Code Online (Sandbox Code Playgroud)

请参阅本页底部

您可以将其与常规类型注释一起使用,如下所示。

/** @type {HTMLCanvasElement} */
var buffered_canvas = /** @type {HTMLCanvasElement} */ (document.createElement("canvas"));
Run Code Online (Sandbox Code Playgroud)

如果 WebStorm 遵循与 Closure 相同的注释约定,这应该可以工作。

无法找到任何真正的规范,例如 HTMLElement 及其具有的属性或 createCanvas 的方法签名以及它返回的类型。

MDN不错,标准也可以看WHATWGW3C


Jay*_*ris 5

两全其美,使用管道运算符将类型设置为 或|

/** @type {HTMLCanvasElement|HTMLElement} */
Run Code Online (Sandbox Code Playgroud)

现在,您的 IDE 将会识别这两种继承的方法。

这样做是可以的,因为HTMLCanvasElement实际上扩展了HTMLElement. 当您这样做时,您是在告诉 IDE 2 件事:

  1. 首先你有 aHTMLCanvasElement因为我们知道HTMLElement返回的 oncreateElement('canvas')是从 a 转换为new HTMLCanvasElement()to的HTMLElement。这样就满足了你的第二个问题:

当我将其更改为 HTMLElement 类型时,它会抱怨 HTMLElement 上未定义宽度和高度属性。

  1. 其次,你有一个HTMLElement因为继承HTMLCanvasElement.prototype = new HTMLElement(),所以这将满足你的第一个问题:

当我将 buffered_canvas 注释为 HTMLCanvasElement 类型时,它抱怨 createElement 返回一个无法分配给 HTMLCanvasElement 的 HTMLElement。

编辑

进一步审查准确性,这是 PHPStorm (我假设也是 WebStorm)正在使用的document.createElement

/**
@param {string} tagName
@return {Element}
*/
Document.prototype.createElement = function(tagName) {};
Run Code Online (Sandbox Code Playgroud)

这是矛盾的,当你将鼠标悬停在该方法上时,createElement你会在弹出窗口中看到以下内容

[ HTMLElement ] Document.prototype.createElement( [ string ] tagName )
Run Code Online (Sandbox Code Playgroud)

HTMLElement最后,原理和之前的extends一样Element,所以可以使用这个注解

/** @type {Element|HTMLElement|HTMLCanvasElement} */
var buffered_canvas = document.createElement("canvas");
Run Code Online (Sandbox Code Playgroud)