Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get namespace from class

Is it possible within TypeScript to get the namespace of a class?

namespace My.API.DTO {
    export class Something {

        // ID
        public id: number;

        public constructor() { }
    }
}

I can write the following to get class name

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

Outputs

Something

I want the output to be

My.API.DTO.Something

I'm open to using a third party library to help with this. Please note I generate all my TypeScript DTO classes from their C# counterparts using the TypeWriter Visual Studio plugin.

like image 443
wonea Avatar asked Feb 08 '18 15:02

wonea


People also ask

What is namespace constant?

namespace keyword and __NAMESPACE__ constant ¶ In global, un-namespaced code, it contains an empty string. The namespace keyword can be used to explicitly request an element from the current namespace or a sub-namespace. It is the namespace equivalent of the self operator for classes.

What are namespaces in C#?

The namespace keyword is used to declare a scope that contains a set of related objects. You can use a namespace to organize code elements and to create globally unique types.

What type is namespace?

A namespace is a logical design-time naming convenience, used mainly to define scope in an application and organize classes and other types in a single hierarchical structure. From the viewpoint of the runtime, there are no namespaces.

What does :: class do in PHP?

SomeClass::class will return the fully qualified name of SomeClass including the namespace. This feature was implemented in PHP 5.5. It's very useful for 2 reasons. You can use the use keyword to resolve your class and you don't need to write the full class name.


1 Answers

If you have access to the root namespace -- My in your case -- you can recursively patch all classes (all functions actually) with a helper method:

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

You just have to be aware that this patches any function inside the tree since ES6 classes are nothing more. The drawback is that you'll have to patch each namespace root individually since patch(window) will most likely result in a too much recursion error and probably other unwanted side-effects.

Note that instead of using object destructuring you could also call patch like this:

patch(My, 'My');

Demo

like image 55
Tao Avatar answered Sep 21 '22 17:09

Tao