0

I understand that you can not extend the native types like Array and String in TypeScript (TS). I have some small extensions I have written using pure JS, that I would like to expose to TS. For example:

Array.prototype.first = function(testFunction) {
    if( typeof(testFunction) !== 'function' ) {
        return null;
    }

    var result = null;
    this.forEach(function(item){
        if( testFunction(item) ) {
            result = item;
            return;
        }
    });
    return result;
};

This is in Array.js. How do I expose the 'first' function to TS.

I have tried creating an Extensions.d.ts file which contains:

export declare var Array: {
    findItem(callback: Function);
}

And then reference that declaration in my app.ts:

/// <reference path="Extensions.d.ts" />

var x: string[] = new Array();
x.first(function (x) { return false; });

But app.ts doesn't seem to know about the first() function.

Is this possible?

EDIT: Ok, it seems that I need this in my .d.ts file:

interface Array<T> {
    first(callback: (Function : T) => boolean) : T;
}

So I guess I just need the following question answered. Consider:

String.format = function () {
    var formatString = arguments[0];
    if( arguments.length < 2 ) {
        return formatString;
    }
    var args = Array.prototype.slice.call(arguments, 1);
   //do formatting here
   return result;
}

How do I declare the static extensions ones?

sheamus
  • 3,001
  • 4
  • 31
  • 54
  • possible duplicate of [Extending Array in TypeScript](http://stackoverflow.com/questions/12802383/extending-array-in-typescript) – WiredPrairie Apr 05 '14 at 14:30

3 Answers3

1

How do I declare the static extensions ones?

Use module:

module String{
    export var format = function (...args:any[]) {
    var formatString = arguments[0];
    if( arguments.length < 2 ) {
        return formatString;
    }
    var args = Array.prototype.slice.call(arguments, 1);
   //do formatting here
   return result;
}

String.format();
basarat
  • 261,912
  • 58
  • 460
  • 511
0

How do I declare the static extensions ones?

Since TypeScript 1.4 static extensions can be added easily. The TypeScript team changed the lib.d.ts file to use interfaces for all static type definitions.

The static type definitions are named like [Type]Constructor: So if you want to add a static function to type String, then add your definition to StringConstructor.

Definition:

interface StringConstructor
{
    format(s: string, ...args: any[]): string;
}

Implementation:

String.format = function(s: string, ...args: any[]): string
{
    // your implementation here
    return "yourFormattedString";
}

Usage:

var s: string = String.format("Hello, {0}", "World");
Stefan Born
  • 720
  • 6
  • 14
  • 1
    Sorry to say, but Visual Studio CTP 6 (February 23rd release) is saying that it's an error there.. Property 'format' does not exists on type 'StringConstructor' – Dovydas Navickas Feb 28 '15 at 01:09
-1

Adding extensions to the built-in types is intentionally difficult because it's really a bad idea.

What happens when your component adds a function called String.format and someone else writes a component that adds something called String.format with different behavior? Last in wins, programs randomly break, chaos ensues. Best case they are so different that your program fails immediately; worst case your program starts subtly corrupting data because it expects String.format to do one thing but it does something slightly different instead (e.g. rounds floating-point numbers instead of truncates).

If you're confident enough that you have determined the absolutely-correct version of what String.format should be, and that no one else who uses your code or whose code you use thinks the same way, then modify lib.d.ts yourself and use that in your projects. When you encounter some other (TypeScript) project that wants to use a custom lib.d.ts, then you can reconcile the differences and determine if you've both decided String.format would be nice to have, but have created competing implementations (since everyone who asks for this feature wants something called String.format, you can assume this will happen).

The best course of action if you think String should have a method called format is to contact the ECMAScript committee and ask them to add it. Short of that, please leave the built-in types alone. They have a hard enough life as is.

Ryan Cavanaugh
  • 209,514
  • 56
  • 272
  • 235
  • This is likely a better comment than a answer (no I didn't down vote). But anyway, yeah, I was aware of all the badness I was doing. But it is application code, that I won't be exporting. I wanted the naming similarity to .Net. But you are correct, there really is no valid reason I couldn't just put MyFavouriteString.format in my code in the places I have String.format. But when I see that in code, it always makes me feel like then all of string should be encapsulate, it feels weird to use two types for the same purpose. But it is food for thought, and I do agree with your points. – sheamus Apr 05 '14 at 17:52