{"action":"created","issue":{"url":"https://api.github.com/repos/angular/angular/issues/11606","repository_url":"https://api.github.com/repos/angular/angular","labels_url":"https://api.github.com/repos/angular/angular/issues/11606/labels{/name}","comments_url":"https://api.github.com/repos/angular/angular/issues/11606/comments","events_url":"https://api.github.com/repos/angular/angular/issues/11606/events","html_url":"https://github.com/angular/angular/issues/11606","id":176950677,"number":11606,"title":"Inheritance for Angular decorators is not well-defined","user":{"login":"alxhub","id":4175141,"avatar_url":"https://avatars.githubusercontent.com/u/4175141?v=3","gravatar_id":"","url":"https://api.github.com/users/alxhub","html_url":"https://github.com/alxhub","followers_url":"https://api.github.com/users/alxhub/followers","following_url":"https://api.github.com/users/alxhub/following{/other_user}","gists_url":"https://api.github.com/users/alxhub/gists{/gist_id}","starred_url":"https://api.github.com/users/alxhub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alxhub/subscriptions","organizations_url":"https://api.github.com/users/alxhub/orgs","repos_url":"https://api.github.com/users/alxhub/repos","events_url":"https://api.github.com/users/alxhub/events{/privacy}","received_events_url":"https://api.github.com/users/alxhub/received_events","type":"User","site_admin":false},"labels":[{"id":375501288,"url":"https://api.github.com/repos/angular/angular/labels/comp:%20core%20&%20compiler","name":"comp: core & compiler","color":"c7def8","default":false},{"id":375497245,"url":"https://api.github.com/repos/angular/angular/labels/freq3:%20high","name":"freq3: high","color":"fbca04","default":false},{"id":375498203,"url":"https://api.github.com/repos/angular/angular/labels/severity3:%20broken","name":"severity3: broken","color":"0052cc","default":false},{"id":130606843,"url":"https://api.github.com/repos/angular/angular/labels/type:%20bug","name":"type: bug","color":"EEEEEE","default":false}],"state":"closed","locked":false,"assignee":{"login":"tbosch","id":690815,"avatar_url":"https://avatars.githubusercontent.com/u/690815?v=3","gravatar_id":"","url":"https://api.github.com/users/tbosch","html_url":"https://github.com/tbosch","followers_url":"https://api.github.com/users/tbosch/followers","following_url":"https://api.github.com/users/tbosch/following{/other_user}","gists_url":"https://api.github.com/users/tbosch/gists{/gist_id}","starred_url":"https://api.github.com/users/tbosch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tbosch/subscriptions","organizations_url":"https://api.github.com/users/tbosch/orgs","repos_url":"https://api.github.com/users/tbosch/repos","events_url":"https://api.github.com/users/tbosch/events{/privacy}","received_events_url":"https://api.github.com/users/tbosch/received_events","type":"User","site_admin":false},"assignees":[{"login":"tbosch","id":690815,"avatar_url":"https://avatars.githubusercontent.com/u/690815?v=3","gravatar_id":"","url":"https://api.github.com/users/tbosch","html_url":"https://github.com/tbosch","followers_url":"https://api.github.com/users/tbosch/followers","following_url":"https://api.github.com/users/tbosch/following{/other_user}","gists_url":"https://api.github.com/users/tbosch/gists{/gist_id}","starred_url":"https://api.github.com/users/tbosch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tbosch/subscriptions","organizations_url":"https://api.github.com/users/tbosch/orgs","repos_url":"https://api.github.com/users/tbosch/repos","events_url":"https://api.github.com/users/tbosch/events{/privacy}","received_events_url":"https://api.github.com/users/tbosch/received_events","type":"User","site_admin":false}],"milestone":null,"comments":35,"created_at":"2016-09-14T16:10:13Z","updated_at":"2016-12-13T03:51:27Z","closed_at":"2016-11-28T22:12:27Z","body":"Currently, when classes with decorators are used in an inheritance chain, the results are undefined.\n\nConsider the following two components:\n\n```\n@Component({selector: 'a', inputs: ['metaFoo'])\nclass A {\n  @Input() fieldFoo;\n  metaFoo;\n}\n\n@Component({selector: 'b', inputs: ['metaBar']}\nclass B extends A {\n  @Input() fieldBar;\n  metaBar;\n}\n```\n\nCurrently, using component `B` in JIT mode does not cause an error, but only inputs `fieldBar` and `metaBar` will be understood by Angular. This is because the decorators result in properties being defined on the class functions, and those properties are subject to shadowing via prototypical inheritance. So `B.annotations` (where the `@Component` metadata lives) shadows `A.annotations`, and `B.propMetadata` (where the `@Input`s live) shadows `A.propMetadata`.\n\nIf the `@Input() fieldBar` from `B` is removed, however, then `B` will have no property metadata, and so the lookup for`B.propMetadata` will reach `A.propMetadata` via the prototype chain and suddenly the `fieldFoo` input will become visible to Angular.\n\nThere is no provision in the spec for inheritance of decorator metadata. However, Angular could be made to support well-defined rules of inheritance for its own decorators.\n\nHere is one set of rules which I believe covers most of the cases where users attempt to inherit components:\n- Class-level decorators (`@Component` and friends) have their metadata merged according to the merge rules:\n  - Metadata objects are merged property by property.\n  - For properties with primitive values, a subclass value, if present, overwrites a superclass value.\n  - For properties with array values, the arrays are concatenated, superclass first.\n  - If the subclass provides no value, the superclass value, if present, is used.\n- Property-level decorators (`@Input`, etc) on superclasses are included in compilation.\n  - `@Input`s with the same name on the superclass and subclass should have the same behavior as two `@Input`s with the same name on the same class.\n\nApplying these rules would change the behavior of the above example, so component `B` would have all 4 defined inputs recognized.\n\nFor JIT mode, this requires two changes to Angular.\n\nFirst, the class-level decorators would be changed to check for metadata on the superclass, and perform the merging operation if present.\n\nSecondly, the runtime compiler would need to consider superclass metadata when checking for property annotations.\n\nFor the AOT compiler, the semantics would have to be built into the compiler itself as the decorators don't execute during AOT compilation.\n"},"comment":{"url":"https://api.github.com/repos/angular/angular/issues/comments/266633738","html_url":"https://github.com/angular/angular/issues/11606#issuecomment-266633738","issue_url":"https://api.github.com/repos/angular/angular/issues/11606","id":266633738,"user":{"login":"tycho01","id":3059397,"avatar_url":"https://avatars.githubusercontent.com/u/3059397?v=3","gravatar_id":"","url":"https://api.github.com/users/tycho01","html_url":"https://github.com/tycho01","followers_url":"https://api.github.com/users/tycho01/followers","following_url":"https://api.github.com/users/tycho01/following{/other_user}","gists_url":"https://api.github.com/users/tycho01/gists{/gist_id}","starred_url":"https://api.github.com/users/tycho01/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tycho01/subscriptions","organizations_url":"https://api.github.com/users/tycho01/orgs","repos_url":"https://api.github.com/users/tycho01/repos","events_url":"https://api.github.com/users/tycho01/events{/privacy}","received_events_url":"https://api.github.com/users/tycho01/received_events","type":"User","site_admin":false},"created_at":"2016-12-13T03:51:27Z","updated_at":"2016-12-13T03:51:27Z","body":"@benelliott: I'd love this as well; when using my inheritance method having to redeclare all parent dependencies on each (grand-)child was definitely a point of frustration to me. Thank you for adding this suggestion."}}
{"actor":{"display_login":"tycho01"}}