Extending Object.prototype with TypeScript Extending Object.prototype with TypeScript javascript javascript

Extending Object.prototype with TypeScript


I used to have:

// See if an array contains an objectArray.prototype.contains = function (obj) {    var i = this.length;    while (i--) {        if (this[i] === obj) {            return true;        }    }    return false;}

in order to make that code compile with typescript I added the line:

interface Array {    contains(obj: Object): boolean;}

Thanks basarat!


This bug is fixed in TS 0.9.0 alpha as you can see below: no error in Ts 0.9.0 alpha

The playground is still running 0.8.3.

This basically happens because methods on some key interfaces ( Object, Number, String ) etc get cached as a performance optimization.

If you run this. The first time it loads you will not see that error. Try It.

As soon as you make an edit to that code, the parser goes through the code again, and since it cached the old interface definition sees a duplicate function definition and then effectively blows up. The more edits you make to that file the more complicated the error statement will get.


I have extended the Array the same way and faced a big problem when s a party was using for i in ... to loop over it. Now you can't control every third party code and these bugs could get really annoying so I suggest a better aprocach:

interface Array<T> {   crandom(): T;}/** Retrieve a random element from the list */ Object.defineProperty(Array.prototype, 'crandom', { value: function() {    let index = Math.floor(Math.random() * this.length);    return this[index];}});

Now by using Object.defineProperty your new property won't be enumerated over and it is safe. The above code pretty much gives a random element from the array. I made another one too which pops a random element from array:

Object.defineProperty(Array.prototype, 'popRandom', { value: function() {    let index = Math.floor(Math.random() * this.length);    let result = this[index];    this.splice(index, 1);    return result;}});

with Object.defineProperty You get more control over this creation and you can add additional restrictions too.