6

I'm trying to add a method to the Array object in Typescript. I've already found other solutions on SO, but none of those work for me.

My code looks like:

interface Array {
    average(): () => number;
}

Array.prototype.average = () => {
    var sum: number = 0

    for (var i = 0; i < this.length; i++)
        sum += this[i]

    if (this.length)
        return sum / this.length

    return 0
}

And I get the error: The property 'average' does not exist on value of type 'Array'

1

3 Answers 3

6

Are you only getting an error in Visual Studio? That much is expected due to a bug in extending build-in interfaces. This should work if you're just invoking tsc.exe.

Relatedly, your code is a little off -- your declaration of average describes a function that returns a function that returns a number, rather than returning a number (you want to just write average(): number on that line). Also, because you used => instead of function() { in the implementation, you'll be binding to the wrong this value at runtime. Hope that helps!

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Ryan. No, I'm not using VS, this error appears while compilation with tsc. Also I changed signature of interface and start using function() but still issuing problem.
You need to move that interface declaration to top-level, otherwise you're just declaring a new type called SelfAppraisalCalc.Array. The assignment to Array.prototype can go wherever (as long as it executes, of course).
6

Here is very simple solution (tested with typescript 1.6):

1) Define method with Array type:

interface Array<T> {
    average():number;
}

2) Implement method:

Array.prototype['average'] = function () {
    return this.reduce(function (a, b) {
        if(typeof a !== "number" || typeof b !== "number"){
            throw new Error("avg method applies only on numeric arrays.");
        }
        return a + b;
    }, 0) / this.length;
};

rendered code should be:

Array.prototype.average = function()........

Now you'll be able to call this as:

var arr:number[] = [1, 2, 3, 4, 5, 6];
arr.average()

Comments

4

Vukasin's answer is correct except that because Array, like Number is a native type you need to access it via the global namespace to augment it. so you need to do this...

declare global {
  interface Array<T> {
    average():number;
  }
}

then you can do :-

if(!Array.prototype.average )
{
  Array.prototype.average = function () {
    return this.reduce(function (a, b) {
        if(typeof a !== "number" || typeof b !== "number"){
            throw new Error("avg method applies only on numeric arrays.");
        }
        return a + b;
    }, 0) / this.length;
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.