{"action":"opened","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/2961","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/2961/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/2961/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/2961/events","html_url":"https://github.com/Microsoft/TypeScript/issues/2961","id":71967928,"number":2961,"title":"Suggestion: Merge ambient class and interface declarations.","user":{"login":"rbuckton","id":3902892,"avatar_url":"https://avatars.githubusercontent.com/u/3902892?v=3","gravatar_id":"","url":"https://api.github.com/users/rbuckton","html_url":"https://github.com/rbuckton","followers_url":"https://api.github.com/users/rbuckton/followers","following_url":"https://api.github.com/users/rbuckton/following{/other_user}","gists_url":"https://api.github.com/users/rbuckton/gists{/gist_id}","starred_url":"https://api.github.com/users/rbuckton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rbuckton/subscriptions","organizations_url":"https://api.github.com/users/rbuckton/orgs","repos_url":"https://api.github.com/users/rbuckton/repos","events_url":"https://api.github.com/users/rbuckton/events{/privacy}","received_events_url":"https://api.github.com/users/rbuckton/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/Suggestion","name":"Suggestion","color":"006b75"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-04-29T19:35:54Z","updated_at":"2015-04-29T19:35:54Z","closed_at":null,"body":"# Summary\r\nTo support re-opening classes and built-ins as classes, I have proposed two suggestions (#2957, #2959) to help to better re-classify built-ins as `class` declarations, rather than the current `interface`-`interface`-`var` pattern we are using for built-in \"classes\". However, these changes would break existing projects that currently extend built-ins by re-opening the interfaces of these built-ins. This proposal seeks to support merging these declarations, so that existing code can continue to function.\r\n\r\n# Current State\r\nCurrently, authors can re-open the instance or static-side interface of many built-ins in `lib.d.ts` to add new functionality. For example:\r\n\r\n```ts\r\n// lib.d.ts\r\ninterface Array<T> { /*... */ }\r\ninterface ArrayConstructor { /*...*/ }\r\ndeclare var Array: ArrayConstructor;\r\n\r\n// polyfill.ts\r\ninterface Array<T> {\r\n  includes(value: T): boolean;\r\n}\r\ninterface ArrayConstructor {\r\n  of<T>(...items: T[]): T[];\r\n}\r\n\r\nArray.prototype.includes = function (value: any) { return this.indexOf(value) != -1; }\r\nArray.of = function<T> (...items: T[]) { return items; }\r\n```\r\n\r\nThe proposals in #2957 and #2959 would break existing libraries without some remediation method.\r\n\r\n# Proposal\r\nI propose two steps to resolve this:\r\n\r\n* Allow you to re-open the interface for the instance side of a class.\r\n* Automatically generate a named interface for the static side of an ambient class declaration in the same lexical scope.\r\n\r\n## Re-open instance-side\r\nRe-opening the instance-side of a class would be possible by merging interfaces with ambient class declarations in the same lexical scope:\r\n\r\n```ts\r\n// lib.d.ts\r\ndeclare class Array<T> { /* ... */ }\r\n\r\n// polyfill.ts\r\ninterface Array<T> {\r\n  include(value: T): boolean;\r\n}\r\n```\r\n\r\n# Automatic static-side interface\r\nFor backwards-compatibility, we could auto-generate a constructor interface for an ambient class declaration. As this is really intended to be a backwards-compatibility feature, we could opt to enable this only when we encounter a triple-slash directive. This would allow us to not only use this for our own `lib.d.ts`, but also allow third parties to use this directive if need to migrate their existing declarations to support these new features.\r\n\r\n```ts\r\n// lib.d.ts\r\n/// <reference auto-static-interface=\"true\" />\r\ndeclare class Array<T> { /* ... */ }\r\n// Creates an `ArrayConstructor` symbol for the static interface of Array\r\n\r\n// polyfill.ts\r\ninterface ArrayConstructor {\r\n  of(...args: T[]): T[];\r\n}\r\n```"}}