从类中获取命名空间

won*_*nea 17 typescript typescript2.7

TypeScript中是否可以获取类的命名空间?

namespace My.API.DTO {
    export class Something {

        // ID
        public id: number;

        public constructor() { }
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以编写以下内容来获取类名

console.log(My.API.DTO.Something.name);
Run Code Online (Sandbox Code Playgroud)

输出

某物

我想要输出

My.API.DTO.Something

我愿意使用第三方库来帮助解决这个问题.请注意我使用TypeWriter Visual Studio插件从他们的C#对应物生成我的所有TypeScript DTO类.

Nat*_*end 7

不幸的是,我认为答案是否定的. 如果将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 = {}));
Run Code Online (Sandbox Code Playgroud)

由于这是您必须使用的所有内容(所有TypeScript类型信息在编译阶段都会消失),因此我认为没有任何理智的方法可以从类中向后工作以获取其命名空间链.

根据您的使用情况,您可以使用类装饰器之类的东西将元数据附加到类并在运行时访问它.这只有在您控制要检查的类时才有效.


*有可能递归循环遍历全局范围内的所有对象,直到找到类的构造函数的位置.例如,您的Something类可以在(在浏览器中)找到window.My.API.DTO.Something.


Tao*_*Tao 7

如果您可以访问根命名空间 - 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
Run Code Online (Sandbox Code Playgroud)

你只需要知道这会修补树中的任何函数,因为ES6类只不过了.缺点是您必须单独修补每个命名空间根,因为patch(window)这很可能会导致过多的递归错误,并可能导致其他不必要的副作用.

请注意,您可以patch像这样调用而不是使用对象解构:

patch(My, 'My');
Run Code Online (Sandbox Code Playgroud)

演示