Search code examples
typescriptannotationsprototype-chainreflect-metadata

reflect-metadata Reflect.getMetadata() method doesn't return metadata on the prototype chain of provided object


I'm using reflect-metadata 0.1.2. I have a parent class as "MyCustom".

export class MyCustom {}

My "Home" component class extend this "MyCustom" class.

@Component({
  selector: 'home',
  templateUrl: './app/components/home/home.html',
  styleUrls: ['./app/components/home/home.css']
})
export class Home extends MyCustom {
}

My intention is to get metadata of all the classes that extend "MyCustom" class using following method call.

let annotations = Reflect.getMetadata('annotations', MyCustom);

The comments on the method Reflect.getMetadata() says,

Gets the metadata value for the provided metadata key on the target object or its prototype chain.

However I get nothing. If I add @Component to "MyCustom" class like below,

@Component({
  selector: 'hello'
})
export class MyCustom {}

I get one result that is the annotation on "MyCustom".

Why am I not getting annotations on subclasses ? Any help is highly appreciated.


Solution

  • The metadata is saved for Home and not for MyCustom, and the inheritance has no effect here.

    What you can probably do, is to have your own decorator which will add metadata for the parent class and then call the Component decorator with the needed values.
    Something like:

    function MyComponent(props: any) {
        return (ctor) => {
            Reflect.defineMetadata('annotations', ctor.prototype.name, ctor.prototype);
            return Component(props)(ctor);
        }
    }
    
    @MyComponent({
        selector: 'home',
        templateUrl: './app/components/home/home.html',
        styleUrls: ['./app/components/home/home.css']
    })
    class Home extends MyCustom {}
    

    I haven't tested it, and haven't done anything similar before, but it should probably work.


    Why don't you use a "registry"?
    Have something like this:

    const REGISTRY: { [name: string]: MyCustom } = {};
    

    Then, for each such component register it:

    class Home extends MyCustom {
        ...
    }
    
    REGISTRY["home"] = Home;
    

    The registry and the components don't have to be in the same file, as long as you import it where needed.

    Then from your main component it's easy to have all of those components.