Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: Merge ambient class and interface declarations. #2961

Closed
rbuckton opened this issue Apr 29, 2015 · 1 comment
Closed

Suggestion: Merge ambient class and interface declarations. #2961

rbuckton opened this issue Apr 29, 2015 · 1 comment
Labels
Fixed A PR has been merged for this issue Suggestion An idea for TypeScript

Comments

@rbuckton
Copy link
Member

Summary

To 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.

Current State

Currently, authors can re-open the instance or static-side interface of many built-ins in lib.d.ts to add new functionality. For example:

// lib.d.ts
interface Array<T> { /*... */ }
interface ArrayConstructor { /*...*/ }
declare var Array: ArrayConstructor;

// polyfill.ts
interface Array<T> {
  includes(value: T): boolean;
}
interface ArrayConstructor {
  of<T>(...items: T[]): T[];
}

Array.prototype.includes = function (value: any) { return this.indexOf(value) != -1; }
Array.of = function<T> (...items: T[]) { return items; }

The proposals in #2957 and #2959 would break existing libraries without some remediation method.

Proposal

I propose two steps to resolve this:

  • Allow you to re-open the interface for the instance side of a class.
  • Automatically generate a named interface for the static side of an ambient class declaration in the same lexical scope.

Re-open instance-side

Re-opening the instance-side of a class would be possible by merging interfaces with ambient class declarations in the same lexical scope:

// lib.d.ts
declare class Array<T> { /* ... */ }

// polyfill.ts
interface Array<T> {
  include(value: T): boolean;
}

Automatic static-side interface

For 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.

// lib.d.ts
/// <reference auto-static-interface="true" />
declare class Array<T> { /* ... */ }
// Creates an `ArrayConstructor` symbol for the static interface of Array

// polyfill.ts
interface ArrayConstructor {
  of(...args: T[]): T[];
}
@mhegazy
Copy link
Contributor

mhegazy commented Aug 7, 2015

This has been fixed by #3333

@mhegazy mhegazy closed this as completed Aug 7, 2015
@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Fixed A PR has been merged for this issue Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants