【问题标题】:TypeScript strips down comments and spoils JSDoc documentationTypeScript 去除注释并破坏 JSDoc 文档
【发布时间】:2016-05-12 13:14:06
【问题描述】:

目标是从 TypeScript 代码中获取 JSDoc 文档。 TypeDoc(TypeScript 文档解决方案)的文档质量是不可接受的,因为文档是针对 JS 用户的,不应该充斥着特定于 TypeScript 实现(接口等)的细节。

目前转译为 ES6 并从 JS 文件生成文档在很大程度上可以解决问题。没有赋值的属性除外。看起来,

class A {
    /**
     * @private
     * @var _a
     */
    private _a;

    /**
     * @public
     * @var a
     */
    public a = true;
}

正在被转译为

class A {
    constructor() {
        /**
         * @public
         * @var a
         */
        this.a = true;
    }
}

虽然我期待类似的东西

class A {
    constructor() {
        /**
         * @private
         * @var _a
         */

        /**
         * @public
         * @var a
         */
        this.a = true;
    }
}

class A {
    /**
     * @private
     * @var _a
     */

    constructor() {
        /**
         * @public
         * @var a
         */
        this.a = true;
    }
}

如何为 TypeScript 中未分配的类成员提供 cmets(尤其是 JSDoc)?有没有什么技巧可以让 cmets 保持原位(即使转译代码中没有 private _a;)?

【问题讨论】:

  • 请问您为什么需要这个功能?当然有一些技巧和变通方法可以将这些 cmets 保持在适当的位置,但目前我认为这绝对没有理由存在。
  • @JohnWhite 除了从转译的 ES6 之外,我还没有找到在 TypeScript 中生成 JSDoc 文档的好方法。由于这种行为,一堆属性仍然没有记录。

标签: typescript jsdoc jsdoc3


【解决方案1】:

解决方法:

class A {
    /**
     * @private
     * @var _a
     */
    private _b = undefined;

    /**
     * @public
     * @var a
     */
    public a = true;
}

[Playground]

问题:

如何为 TypeScript 中未分配的类成员提供 cmets(尤其是 JSDoc)?

如果你看看负责构造函数生成的源代码:

  • emitConstructor [line]
  • |--- emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ false)); [line]
  • |------ getInitializedProperties [line]

您可以看到,无法自定义行为。

现有的文档生成工具

硬核方法:

TypeScript 提供编译器 API:https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API。可能,您可以遍历源代码并生成您喜欢的任何文档。

【讨论】:

  • 是的,谢谢,这就是解决方案。但它会产生大量的垃圾代码(并且可能会破坏inhasOwnProperty 部分)。
  • 您可以在您的问题中添加所需的输出吗?
【解决方案2】:

有没有什么技巧可以让 cmets 保持原位?

您几乎可以肯定实际上并不想要这个。例如,以下代码不产生任何输出:

/** an interface */
interface Q { }

如果编译器要保留文档,它们在许多(几乎所有)情况下都是多余的和误导性的。如果它出现在class C 上方,那么该文档似乎适用于该类(如果该类没有自己的文档,则更令人困惑)。如果我正在阅读您问题中的示例,我想知道this.a 实际上是第一个文档声称的@private,还是@public。其他程序员和您的工具没有正确的方法来解释这些杂散的文档。

当 TS 和 JS 之间存在直接对应关系时,编译器会保留文档,严格来说是因为这样做没有害处(即使实用程序很少)。但它不会也不应该保留与它们适用的代码分离的文档。

查看文档的最佳位置是直接在 TypeScript 源代码中(在您的编辑器中,或通过源映射)。您的源是 TypeScript 文件,而不是发出的 JS:使用 a TypeScript doc generator。编译或转译的代码对于文档来说不是一个有用的地方,并且保留问题所询问的特定文档会产生误导。

【讨论】:

  • 这可能是正确的,但我确实想要这个。这个问题首先指的是 JSDoc cmets。它们适用于不必成为代码阅读器的文档阅读器。将它们转译为 JS 是生成 JSDoc 文档的方式,而不是阅读它。注意@var 标签的使用,它被放置在那里是为了帮助被替换的 cmets 被正确解析。
  • 您正在 TS 中编写一个 JS 库,并且您想要纯 JS 文档 - 完全合理。您希望 TS 编译器可能会以一种有助于您使用 JSDoc 读取转译 JS 的解决方法的方式生成代码。它没有这样做,我同意它令人失望,但有时最有帮助的答案就是“你不能”(但我不能只发布那个)。与其尝试更改编译器,不如向 TypeDoc 项目提交一个请求,以获取省略与打字稿相关的文档的标志?似乎是一个合理的要求。然后你就不需要多余的@public@var
【解决方案3】:

有什么技巧可以让 cmets 保持原位吗?

有点。您可以显式指定默认构造函数并将其他分离的 cmets 附加到它。变化:

class MyClass {
    /**
     * @private
     * @var _a
     */
    private _a;

    /**
     * @private
     * @var _b
     */ 
    private _b;
}

到:

class MyClass {
    /**
     * @private
     * @var _a
     */

    /**
     * @private
     * @var _b
     */

    constructor() {}

    private _a;

    private _b;
}

这将改变输出:

var MyClass = (function () {
    function MyClass() {
    }
    return MyClass;
})();

到:

var MyClass = (function () {
    /**
     * @private
     * @var _a
     */
    /**
     * @private
     * @var _b
     */
    function MyClass() {
    }
    return MyClass;
})();

这正是您想要的。这是可以找到的“最干净的技巧”。

【讨论】:

  • 感谢您的建议,因此会损害风格,但可以作为临时解决方案接受,直到它会在 TypeScript 中自行解决。
  • 这充其量只是部分解决方案。获取最后一个代码 sn-p 中显示的输出,只需在MyClass 前面添加必要的/** @class */,然后使用jsdoc 处理。在文档中,您将获得该类,但它没有任何属性。 jsdoc 无法使用作为 IIFE 一部分的 doclet。为了被 jsdoc 使用,他们需要有 @name 标签来给出一个全名,使他们成为 MyClass 的成员。
【解决方案4】:

将_a定义为未定义,如下所示:

class A {
    /**
     * @private
     * @var _a
     */
    private _a = undefined;

    /**
     * @public
     * @var a
     */
    public a = true;
}

编译成

class A {
    constructor() {
        /**
         * @private
         * @var _a
         */
        this._a = undefined;
        /**
         * @public
         * @var a
         */
        this.a = true;
    }
}

编辑:

如果你希望 hasOwnProperty 在构造函数中的行为完全相同,请删除 _a:

class A {
    /**
     * @private
     * @var _a
     */
    private _a = undefined;

    /**
     * @public
     * @var a
     */
    public a = true;

    constructor() {
        delete this._a;
    }
}

编译成

var A = (function () {
    function A() {
        /**
         * @private
         * @var _a
         */
        this._a = undefined;
        /**
         * @public
         * @var a
         */
        this.a = true;
        delete this._a;
    }
    return A;
}());

【讨论】:

    猜你喜欢
    • 2015-06-02
    • 2017-10-01
    • 2015-10-04
    • 2015-12-22
    • 2011-11-02
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    相关资源
    最近更新 更多