0

I have created a polyfill for the JavaScript Array;

if (Array.prototype.remove !== 'function') {
    Array.prototype.remove = function (value) {
        var idx = this.indexOf(value);
        if (idx !== -1) {
            return this.splice(idx, 1);
        }
        return false;
    };
}

Now I am upgrading the original JavaScript project to a TypeScript project and the tsc complains about the usage of the .remove method:

class Archive {
   documents: DocInfo[] = [];  // <-- Array of class DocInfo

   addDocument(document: DocInfo) {
      ...
   }

   deleteDocument(document: DocInfo) {
      this.documents.remove(document);
                     ^^^^^^
                     tsc complains here: TS2339:Property 'remove' does not exist on type 'DocInfo[]'
   }
}

How can I tell the tsc about this extension?

I tried creating a typings file, but without any success:

declare module 'Array' {
    export function removeByAttr(propertyName: string, propertyValue: any);
}

Thanks

mvermand
  • 5,829
  • 7
  • 48
  • 74

2 Answers2

1

The typings should extend Array<T> interface:

interface Array<T> {
    remove(item: T): boolean;
}
Aleksey L.
  • 35,047
  • 10
  • 74
  • 84
  • Adding this code in a .d.ts file in my /typings folder did the trick! – mvermand Nov 17 '16 at 09:14
  • Note, please suggest to use less generic name. This can have issues and might override original `Array.remove` function. – Rajesh Nov 17 '16 at 09:36
  • @Rajesh, `Array` has no `remove` function. And anyway the question is how to add typings. – Aleksey L. Nov 17 '16 at 11:41
  • Adding generic names in prototype is considered as bad practice because if its added in future, your code will override it. Also I just asked you to add this caveat – Rajesh Nov 17 '16 at 11:44
  • @AlekseyL. It will use native code, but overridden typing. that's a problem – OwnageIsMagic Apr 02 '17 at 22:29
1

Extending the Array class with an interface it's simple, you could try something like this:

Playground

    interface Array<T> {
   remove(o: T): Array<T>;
}

Array.prototype.remove = function (o) {

    var idx = this.indexOf(o);
        if (idx !== -1) {
            return this.splice(idx, 1);
        }
    return this;
}

class DocInfo { 
    name: string ;
    constructor(name) { 
        this.name = name;
    }
}

class Archive {
   documents: DocInfo[] = []; 
   addDocument(document: DocInfo) {
       this.documents.push(document);
   }
   deleteDocument(document: DocInfo) {
      this.documents.remove(document);
   }
   printDocuments() { 
       this.documents.forEach((item: DocInfo) => { 
           console.log(item.name);
       });

   }
}

const a = new Archive();
const _1 = new DocInfo('1');
const _2 = new DocInfo('2');

a.addDocument(_1);
a.addDocument(_2);
a.printDocuments();
a.deleteDocument(_1);
console.log('*********************');
a.printDocuments();
console.log('*********************');
a.addDocument(_1);
a.deleteDocument(_2);
a.printDocuments();
ale
  • 10,012
  • 5
  • 40
  • 49
  • is there a way to make an array extension for only arrays that contain particular classes? ie. MyClass[] ? – Gillardo Sep 14 '17 at 08:07
  • @Gillardo sure with constraint, take a look at https://www.typescriptlang.org/docs/handbook/generics.html *Using Type Parameters in Generic Constraints* – ale Sep 14 '17 at 08:15