{"action":"created","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3154","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3154/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3154/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3154/events","html_url":"https://github.com/Microsoft/TypeScript/issues/3154","id":76085429,"number":3154,"title":"Unable to install wrapper function from parameter decorator","user":{"login":"bryanforbes","id":204106,"avatar_url":"https://avatars.githubusercontent.com/u/204106?v=3","gravatar_id":"","url":"https://api.github.com/users/bryanforbes","html_url":"https://github.com/bryanforbes","followers_url":"https://api.github.com/users/bryanforbes/followers","following_url":"https://api.github.com/users/bryanforbes/following{/other_user}","gists_url":"https://api.github.com/users/bryanforbes/gists{/gist_id}","starred_url":"https://api.github.com/users/bryanforbes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bryanforbes/subscriptions","organizations_url":"https://api.github.com/users/bryanforbes/orgs","repos_url":"https://api.github.com/users/bryanforbes/repos","events_url":"https://api.github.com/users/bryanforbes/events{/privacy}","received_events_url":"https://api.github.com/users/bryanforbes/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/Question","name":"Question","color":"d4c5f9"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":7,"created_at":"2015-05-13T18:50:06Z","updated_at":"2015-05-29T13:34:10Z","closed_at":null,"body":"While attempting to create a decorator for checking if a parameter is `null` and throwing, I found that the code emitted is overwriting the wrapper function I'm installing.\r\n\r\n```ts\r\nfunction throwIfNull(target: any, key: string, index: number) {\r\n\tlet original = target[key];\r\n\treturn function () {\r\n\t\tif (arguments[index] === null) {\r\n\t\t\tthrow new TypeError(`Argument #${index} must be defined and not null`);\r\n\t\t}\r\n\t\toriginal.apply(this, arguments);\r\n\t};\r\n}\r\n\r\nclass Foo {\r\n\tbar(@throwIfNull baz?: any) {\r\n\t\tconsole.log('here');\r\n\t}\r\n}\r\n\r\nvar foo = new Foo();\r\nfoo.bar(null);\r\n```\r\n\r\nThe emitted JavaScript (ES5) is:\r\n\r\n```js\r\nvar __decorate = this.__decorate || function (decorators, target, key, desc) {\r\n    if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") return Reflect.decorate(decorators, target, key, desc);\r\n    switch (arguments.length) {\r\n        case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);\r\n        case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);\r\n        case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);\r\n    }\r\n};\r\nvar __param = this.__param || function(index, decorator) { return function (target, key) { decorator(target, key, index); } };\r\nfunction throwIfNull(target, key, index) {\r\n    var original = target[key];\r\n    return function () {\r\n        if (arguments[index] === null) {\r\n            throw new TypeError(\"Argument #\" + index + \" must be defined and not null\");\r\n        }\r\n        original.apply(this, arguments);\r\n    };\r\n}\r\nvar Foo = (function () {\r\n    function Foo() {\r\n    }\r\n    Foo.prototype.bar = function (baz) {\r\n        console.log('here');\r\n    };\r\n    Object.defineProperty(Foo.prototype, \"bar\",\r\n        __decorate([\r\n            __param(0, throwIfNull)\r\n        ], Foo.prototype, \"bar\", Object.getOwnPropertyDescriptor(Foo.prototype, \"bar\")));\r\n    return Foo;\r\n})();\r\nvar foo = new Foo();\r\nfoo.bar(null);\r\n```\r\n\r\nThe problem stems from `__decorate` returning the original property descriptor because the function returned by `__param` doesn't return anything. This causes the original property descriptor to be installed back onto `Foo.prototype`."},"comment":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/comments/106803647","html_url":"https://github.com/Microsoft/TypeScript/issues/3154#issuecomment-106803647","issue_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/3154","id":106803647,"user":{"login":"remojansen","id":10656223,"avatar_url":"https://avatars.githubusercontent.com/u/10656223?v=3","gravatar_id":"","url":"https://api.github.com/users/remojansen","html_url":"https://github.com/remojansen","followers_url":"https://api.github.com/users/remojansen/followers","following_url":"https://api.github.com/users/remojansen/following{/other_user}","gists_url":"https://api.github.com/users/remojansen/gists{/gist_id}","starred_url":"https://api.github.com/users/remojansen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/remojansen/subscriptions","organizations_url":"https://api.github.com/users/remojansen/orgs","repos_url":"https://api.github.com/users/remojansen/repos","events_url":"https://api.github.com/users/remojansen/events{/privacy}","received_events_url":"https://api.github.com/users/remojansen/received_events","type":"User","site_admin":false},"created_at":"2015-05-29T13:34:10Z","updated_at":"2015-05-29T13:34:10Z","body":"I'm having a similar issue. I want to be able to do observe the decorated parameter. \r\n```\r\nclass Person { \r\n\t\r\n\tpublic name: string;\r\n\tpublic surname: string;\r\n\t\r\n\tconstructor(name : string, surname : string) { \r\n\t\tthis.name = name;\r\n\t\tthis.surname = surname;\r\n\t}\r\n\t\r\n\tpublic saySomethingAsync(something: string, @logParameter cb: (said : string) => void) { \r\n\t\tcb(this.name + \" \" + this.surname + \" says: \" + something); \r\n\t}\r\n\r\n}\r\n```\r\nMy idea was to override `saySomethingAsync`:\r\n\r\nIf I try to create a new property descriptor for the `saySomethingAsync` function:\r\n```\r\nfunction logParameter(target: any, key: string, index: number) {\r\n\t\r\n\tvar descriptor = Object.getOwnPropertyDescriptor(target, key);\r\n\tvar originalMethod = descriptor.value; \r\n\t\r\n\tdescriptor.value = function (...args: any[]) { \r\n\t\t// 1. override args[index] so every time it is invoked it will be logged in the console\r\n\t\t// 2. invoke originalMethod \r\n\t}\r\n\t\r\n\treturn descriptor; // return is ignored \r\n}\r\n```\r\nI can't override the descriptor because the `__param` function is not returning:\r\n```\r\nvar __param = this.__param || function (index, decorator) {\r\n\treturn function (target, key) {\r\n\t\tdecorator(target, key, index);  // missing return ???\r\n\t}\r\n};\r\n```\r\nI also tried a \"brute force overriding\":\r\n```\r\nfunction logParameter(target: any, key: string, index: number) {\r\n\r\n\tvar originalMethod = target[key];\r\n\t\r\n\ttarget[key] = function(...args) {\r\n\t\t// 1. override args[index] so every time it is invoked it will be logged in the console\r\n\t\t// 2. invoke originalMethod \r\n\t}\r\n}\r\n```\r\nBut that doesn't work either because after I override the method it is overridden again using a copy of the original descriptor (when `Object.defineProperty` in the class delcaration is executed). \r\n\r\nAdding return to `__param` would solve my problem. \r\n\r\nThe solution above:\r\n```\r\nclass Foo {\r\n  @validate\r\n  bar(@throwIfNull baz) {}\r\n}\r\n```\r\nFeels non intuitive and unnatural for me.\r\n\r\n Why did you decide that `__param` should not return?\r\n\r\n "}}