【问题标题】:What does a proceeding exclamation mark do for JSDoc @type tag?JSDoc @type 标记前的感叹号有什么作用?
【发布时间】:2019-05-15 09:56:45
【问题描述】:

VS Code 将以下内容解析为没有感叹号,没有任何错误:

const el = /** @type {HTMLElement!} */ (document.getElementById("abc"));

它有什么作用? JSDoc 官方文档说only about preceding marks:

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

不确定继续标记的作用。

【问题讨论】:

    标签: javascript visual-studio-code google-closure-compiler jsdoc


    【解决方案1】:

    TLDR!HTMLElementHTMLElement! 实际上是同一个注解。


    const el = /** @type {HTMLElement!} */ (document.getElementById("abc"));
    

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

    这一行的作者应该 100% 确信存在 id 为 abc 的元素,因为在进行此转换后,闭包编译器会将这种类型视为 HTMLElement,而不是可能的 @ 987654329@或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;
                                         ^
    

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

    【讨论】:

    • 哦,所以!HTMLElementHTMLElement! 完全一样!
    • 在类型符号之后使用它对我来说更有意义,因为在常规 JS 中使用前面的感叹号可以标记相反的内容。 (!true === false) 等于:true。还有一点:从语法的角度来看,当你在类型定义之后添加问号时,你会质疑它是否为真。
    • 同意 Remi,根据我的经验,!? 运算符几乎总是在类型之前。不过,我认为您的示例最好重述:!(true == false).
    猜你喜欢
    • 2011-04-14
    相关资源
    最近更新 更多