前面的感叹号对 JSDoc @type 标记有什么作用?
What does a proceeding exclamation mark do for JSDoc @type tag?
VS Code 解析以下内容,就好像没有感叹号一样,没有任何错误:
const el = /** @type {HTMLElement!} */ (document.getElementById("abc"));
它有什么作用?官方 JSDoc 文档说 only about preceding marks:
Indicates that the value is of the specified type, but cannot be null.
不确定后续标记的作用。
TLDR: !HTMLElement
和 HTMLElement!
实际上是相同的注释。
const el = /** @type {HTMLElement!} */ (document.getElementById("abc"));
是类型转换。它说 document.getElementById("abc")
是一个 HTMLElement,而不是 null。添加注释可能是因为 getElementById returns HTMLElement 或 null。
这一行的作者应该 100% 确信 id 为 abc
的元素存在,因为在进行此转换之后,Closure 编译器会将此类型视为 HTMLElement
, 而不是 HTMLElement
或 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 it through the 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;
^
请注意,body
由 document.querySelector
返回,类型为 {?Element}
,我们说过编译器理解可以是 Element
或 null
、a.k.a。 Element|null
。这个例子表明,符号也可以表示为 ?Element
或 Element?
.
VS Code 解析以下内容,就好像没有感叹号一样,没有任何错误:
const el = /** @type {HTMLElement!} */ (document.getElementById("abc"));
它有什么作用?官方 JSDoc 文档说 only about preceding marks:
Indicates that the value is of the specified type, but cannot be null.
不确定后续标记的作用。
TLDR: !HTMLElement
和 HTMLElement!
实际上是相同的注释。
const el = /** @type {HTMLElement!} */ (document.getElementById("abc"));
是类型转换。它说 document.getElementById("abc")
是一个 HTMLElement,而不是 null。添加注释可能是因为 getElementById returns HTMLElement 或 null。
这一行的作者应该 100% 确信 id 为 abc
的元素存在,因为在进行此转换之后,Closure 编译器会将此类型视为 HTMLElement
, 而不是 HTMLElement
或 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 it through the 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;
^
请注意,body
由 document.querySelector
返回,类型为 {?Element}
,我们说过编译器理解可以是 Element
或 null
、a.k.a。 Element|null
。这个例子表明,符号也可以表示为 ?Element
或 Element?
.