进行中的感叹号对 JSDoc @type 标签有什么作用?

Kag*_*ght 2 javascript google-closure-compiler jsdoc visual-studio-code

VS Code 解析以下内容,就好像没有感叹号一样,没有任何错误:

const el = /** @type {HTMLElement!} */ (document.getElementById("abc"));
Run Code Online (Sandbox Code Playgroud)

它有什么作用?官方 JSDoc 文档仅说明了前面的标记

表示该值属于指定类型,但不能为空。

不确定后续标记的作用。

Gra*_*ath 5

TLDR!HTMLElementHTMLElement!是一样的注释,实际而言。


const el = /** @type {HTMLElement!} */ (document.getElementById("abc"));
Run Code Online (Sandbox Code Playgroud)

是类型转换。它说这document.getElementById("abc")是一个 HTMLElement,而不是 null。可能添加了注释,因为getElementById返回 HTMLElement 或 null。

这行代码的作者应该 100% 相信一个 id 为 的元素abc存在,因为在进行这个转换之后,闭包编译器会将此类型视为 an HTMLElement,而不是可能的 an HTMLElementor null

转换中使用的类型与转换外的类型遵循相同的规则,因此为了演示直接使用这些类型,下面的示例不使用转换。

正如 OP 所说,在 Closure Compiler 中,感叹号表示该类型必须存在,而不能是null. 此外,问号意味着它可能是类型,也可能是null.

以下面的代码为例:

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @output_file_name default.js
// @formatting pretty_print
// ==/ClosureCompiler==

const body = document.querySelector('body');

const /** @export {Element!} */ n1 = body;
const /** @export {!Element} */ n2 = body;
const /** @export {Element} */ n3 = null;
const /** @export {?Element} */ n4 = null;
const /** @export {Element?} */ n5 = null;

console.log({
  n1,
  n2,
  n3,
  n4,
})
Run Code Online (Sandbox Code Playgroud)

通过 Closure Compiler 运行它,以下是编译器生成的警告:

JSC_TYPE_MISMATCH: initializing variable
found   : (Element|null)
required: Element at line 3 character 37
const /** @export {Element!} */ n1 = body;
                                     ^
JSC_TYPE_MISMATCH: initializing variable
found   : (Element|null)
required: Element at line 4 character 37
const /** @export {!Element} */ n2 = body;
                                     ^
Run Code Online (Sandbox Code Playgroud)

请注意,body返回document.querySelector的类型为{?Element} ,我们已经说过编译器可以理解为Elementnull,也就是Element|null。这个例子表明符号也可以表示为?ElementElement?

  • 哦,所以`!HTMLElement` 和`HTMLElement!` 完全一样! (4认同)