Description
Summary
To better support subclassing built-ins, and still support built-ins and pre-ES6 "classes" that can also be called as functions, we should be able to merge the call signatures of ambient function declarations with the static side of a class declaration.
Current state
Currently, if you want to declare an ambient "class" that has both call and construct signatures, you need to use an interface
-interface
-var
pattern, as follows:
// instance-side interface type
interface Array<T> { /*...*/ }
// static-side interface type
interface ArrayConstructor {
<T>(length: number): T[];
new <T>(length: number): T[];
/* ... */
}
// value declaration for constructor
declare var Array: ArrayConstructor;
This is a problem, however as "classes" defined using this pattern cannot be used in the extends
clause of a class declaration in TypeScript.
Proposal
Merge ambient function and class declarations with the same name. Ambient function declarations with the same name as an ambient class declaration in the same lexical scope would contribute their call signatures to the static side of the class declaration. For example:
// lib.d.ts
declare function Array<T>(length: number): T[];
declare class Array<T> {
constructor(length: number);
}
// app.ts
var ar1 = Array(10); // T[]
var ar2 = new Array(10); // T[]
Out of scope
- This proposal does not cover the case where classes in TypeScript today cannot be re-opened. This case is covered in Suggestion: Reopen static and instance side of classes #2957.
- This proposal does not cover the case where authors may have already extended the interface of a built in. This case is covered in Suggestion: Merge ambient class and interface declarations. #2961.