40

Closed

Allow to extend global variables like Date or Object to support libs like sugar.js

description

What: Currently it is only possible to extends the global objects like Date in its type interfaces, but not on its static interfaces (aka global variables).

Why: There are libraries like sugar.js which extending the global objects with some useful functions which are missing in the base library. Its currently not possible (at least as I know) to support them without that.

How: This can be solved by changing lib.d.ts to use FooStatic interfaces instead of object type definitions. Example:

instead of
   declare var Date: {}
it should be
   interface DateStatic: {}
   declare var Date: DateStatic;
Closed Jul 28, 2014 at 11:17 PM by jonturner
As part of our move to GitHub, we're closing our CodePlex suggestions and asking that people move them to the GitHub issue tracker for further discussion. Some feature requests may already be active on GitHub, so please make sure to look for an existing issue before filing a new one.

You can find our GitHub issue tracker here:
https://github.com/microsoft/typeScript/issues

comments

RyanCavanaugh wrote Nov 26, 2012 at 5:54 PM

This sounds like the right thing to do - over to Luke to verify.

chaholl wrote Jan 8, 2013 at 5:01 PM

Can we also have similar support for Function?

Microsoft AJAX extends Function with methods such as createDelegate. Currently there's no way to model that using TypeScript since Function is defined as:

declare var Function: {
new (...args: string[]): Function;
(...args: string[]): Function;
prototype: Function;
}

Can it instead be:

interface StaticFunction {
 new (...args: string[]): Function;
(...args: string[]): Function;
prototype: Function;
}

declare var Function: StaticFunction;

or similar?

jonturner wrote Mar 8, 2013 at 12:32 AM

We're considering allowing declare vars to be extended just like interfaces. If we end up not going down that route, we should definitely make sure the interfaces we aren't allowing to be extended are the ones we intend to be limited, otherwise we should move them to interfaces as originally suggested.

MgSam wrote Apr 24, 2013 at 3:36 PM

Another option would be to allow static and constructor members on interfaces. This would be much more elegant, as you would only need a single interface to describe an entire type:

interface Date: {
    constructor(): Date;
    constructor(value: number): Date;
    constructor(value: string): Date;
    constructor(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date;
    static (): string;
    static prototype: Date;
    static parse(s: string): number;
    static UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number;
    toString(): string;
    toDateString(): string;
    toTimeString(): string;
    toLocaleString(): string;
    toLocaleDateString(): string;
    ...
}

vmadman wrote Dec 19, 2013 at 4:27 AM

I've created a quick gist with my current workaround/solution for using Sugar.js's static extensions. I'm still pretty new to TypeScript, so I'm sure its not the best solution, but I did not see a workaround example in my own search so maybe this will help someone.

Bartvds wrote Mar 8, 2014 at 1:25 PM

Is this still on?

I'd like to rig a definition for the new ES6 language extensions (like the polyfills from es6-shim) but most of it extends native types.

ENikS wrote Apr 4, 2014 at 6:47 AM

I think declare should be open ended same as interface.

jamesnw wrote Apr 4, 2014 at 2:56 PM

Just keep in mind that this introduces one exception to class rules: "super()" calls should not be placed in classes that derive from primitive types. You cannot apply Array's constructor to an object instance. As well, you cannot pass a value to the "String" constructor, and have it populate the character array - this has to be done manually. Another note is that to extend from some primitive types, you HAVE to implement custom "toString()" and/or "toValue()" functions, or the native calls WILL fail (with message "TypeError: String.prototype.toString is not generic"). Doing this for Strings ALSO requires creating YOUR OWN variable to store the underlying value. So if you expect a class to extend "String" and type "new MyString(value)", what should happen? All you end up with is a simple object who's prototype connects with String.prototype, and it would fail to work as expected (in fact, errors will ensue if extended only). If you cannot natively apply the primitive constructors to the derived objects, you need workarounds - and I was recently told that is something TypeScript was not going to allow (not that I'm against it! ;) ).

ChrisLE wrote Apr 8, 2014 at 1:18 PM

Is there smth new? I would like to extend Some objets like String and Array with new static functions and I have read about some months ago, that this will be possible in TS 1.0 but I dont think so.


Regards

Chris

jamesnw wrote Apr 8, 2014 at 10:41 PM

Hi Chris, be sure to read my previous comment. If you want to extend String, you will need to add methods to "String.prototype". You CANNOT inherit from "String" in JavaScript simply by prototype without errors. More needs to be done to make it work (and it will be many times slower).

bgever wrote Oct 7, 2014 at 4:35 AM

Related issue tracking on GitHub: https://github.com/Microsoft/TypeScript/issues/182