Получить пространство имен из класса

Возможно ли внутри TypeScript получить пространство имен класса?

namespace My.API.DTO {
    export class Something {

        // ID
        public id: number;

        public constructor() { }
    }
}

Я могу написать следующее, чтобы получить имя класса

console.log(My.API.DTO.Something.name);

Выходы

Что-то

Я хочу, чтобы результат был

My.API.DTO.Something

Я открыт для использования сторонней библиотеки, чтобы помочь с этим. Обратите внимание, что я сгенерировал все свои классы DScript типа DScript из своих С# -компиляторов, используя плагин TypeWriter Visual Studio.

Ответ 1

К сожалению, я думаю, что ответ отрицательный. '); document.writeln(`constructor name: ${s.constructor.name}`); rel=noreferrer>Если вы сравните свой код типа TypeScript с скомпилированным JavaScript, вы увидите, что пространства имен реализованы с использованием довольно стандартного шаблона модуля JavaScript:

var My;
(function (My) {
    var API;
    (function (API) {
        var DTO;
        (function (DTO) {
            var Something = /** @class */ (function () {
                function Something() {
                }
                return Something;
            }());
            DTO.Something = Something;
        })(DTO = API.DTO || (API.DTO = {}));
    })(API = My.API || (My.API = {}));
})(My || (My = {}));

Так как это все, с чем вам нужно работать (вся информация типа TypeScript исчезает на этапе компиляции), я не думаю, что существует разумный * способ работать назад от класса, чтобы получить свою цепочку пространства имен.

В зависимости от вашего варианта использования вы можете использовать что-то вроде декораторов классов для прикрепления метаданных к классу и доступа к нему во время выполнения. Это будет работать, только если вы контролируете классы, которые хотите проверить.


* Возможно, можно рекурсивно перебрать все объекты в глобальной области действия до тех пор, пока вы не найдете местоположение функции конструктора классов.Например, ваш класс Something можно найти (в браузере) в window.My.API.DTO.Something.

Ответ 2

Если у вас есть доступ к корневому пространству имен - " My в вашем случае - вы можете рекурсивно исправлять все классы (все функции на самом деле) с помощью вспомогательного метода:

const patch = (ns: object, path?: string) => {
    Object.keys(ns).forEach((key) => {
        const value = ns[key];
        const currentPath = path ? '${path}.${key}' : key;
        if (typeof value === 'object') {
            patch(value, currentPath);
        }
        if (typeof value === 'function') {
            Object.defineProperty(value, 'name', {
                value: currentPath,
                configurable: true,
            });
        }
    })
}

namespace My.API.DTO {
    export class Something {

        // ID
        public id: number;

        public constructor() { }
    }
}

patch({ My });

console.log(My.API.DTO.Something.name); // My.API.DTO.Something

Вы просто должны знать, что это исправляет любую функцию внутри дерева, поскольку классы ES6 больше не являются. Недостатком является то, что вам придется исправлять каждый корень пространства имен отдельно, поскольку patch(window), скорее всего, приведет к слишком большой ошибке рекурсии и, возможно, к другим нежелательным побочным эффектам.

Обратите внимание, что вместо использования деструкции объекта вы также можете вызвать patch следующим образом:

patch(My, 'My');

{ Object.keys(ns).forEach((key) => { const value = ns[key]; const currentPath = path? `${path}.${key}`: key; if (typeof value === 'object') { patch(value, currentPath); } if (typeof value === 'function') { Object.defineProperty(value, 'name', { value: currentPath, configurable: true, }); } }) } namespace My.API.DTO { export class Something { //ID public id: number; public constructor() { } } } patch({ My }); console.log(My.API.DTO.Something.name); rel=noreferrer>демонстрация