Подтвердить что ты не робот

TypeScript удаляет комментарии и портит документацию JSDoc

Цель состоит в том, чтобы получить JSDoc-документацию из TypeScript кода. Качество документации из решения для документации 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;
    }
}

Как можно предоставить комментарии (в частности, JSDoc) для неназначенных членов класса в TypeScript? Есть ли уловка, которая могла бы заставить комментарии оставаться на месте (даже если private _a; отсутствует в переводе кода)?

4b9b3361

Ответ 1

Есть ли трюк, который может заставить комментарии оставаться на месте?

Ты почти наверняка этого не хочешь. Например, следующий код не производит вывод:

/** an interface */
interface Q { }

Если компилятор должен был сохранить документы, они во многих (почти всех) случаях были бы лишними и вводящими в заблуждение. Если это появилось выше class C, то документ, похоже, применим к классу (еще более запутанным, если у этого класса не было собственных документов). Если бы я читал пример в вашем вопросе, я бы подумал, был ли this.a на самом деле @private, как утверждал первый документ, или @public. Не существует правильного способа для других программистов и для ваших инструментов интерпретировать эти бродячие документы.

Компилятор сохраняет документы, когда есть прямое соответствие между TS и JS, строго потому, что это не наносит вреда (хотя и очень мало полезности). Но он не должен и не должен сохранять документы, которые отделены от кода, к которому они применяются.

Лучшее место для просмотра документов - непосредственно в источнике TypeScript (в вашем редакторе или через исходные файлы). Это TypeScript файл, который является вашим источником, а не испускаемым JS: используйте a TypeScript doc generator. Скомпилированный или преобразованный код не является полезным местом для документов, и перенос отдельных документов, о которых спрашивает вопрос, будет вводить в заблуждение.

Ответ 2

Обход проблемы:

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

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

[Playground]

Вопрос:

Как можно предоставить комментарии (особенно JSDoc) для неназначенных членов класса в TypeScript?

Если вы посмотрите на исходный код, ответственный за генерацию конструктора:

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

Вы можете видеть, что невозможно настроить поведение.

Существующие инструменты для создания документации

Hardcore:

TypeScript предоставляет API-интерфейс компилятора: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API. Возможно, вы можете перемещать исходный код и генерировать любую документацию, которая вам нравится.

Ответ 3

Есть ли трюк, который может заставить комментарии оставаться на месте?

Несколько. Вы можете явно указать конструктор по умолчанию и присоединить к нему в противном случае отдельные комментарии. Изменение:

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;
})();

Это именно то, что вы хотите. Это "самый чистый трюк", который можно найти.

Ответ 4

Определите _a как undefined, например:

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;
    }
}

Edit:

Если вы хотите, чтобы hasOwnProperty вел себя точно так же delete _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;
}());