Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restrict interface type parameter in method

I'm trying to convey that a method only makes sense when the type parameter of its interface honours a certain constraint. Here's a (non-compiling) example:

interface Array<T> {
    fold<B>(base: B, f: (acc: B, e: T) => B): B
    sum(): T is number
}

Array.prototype.fold = function(base, f) {
    let result = base
    for (let i = 0; i < this.length; i++)
        result = f(result, this[i])
    return result
}

Array.prototype.sum = function() {
    return this.fold(0, (acc, e) => acc + e)
};

[1, 'a', 3].sum() //? 1a3  <-- should be an error!

Here, I was trying to convey that sum only makes sense when T extends number.

like image 699
Hugo Sereno Ferreira Avatar asked Dec 09 '25 17:12

Hugo Sereno Ferreira


1 Answers

You've got the right idea, just the wrong syntax.

This is how you write it.

interface Array<T> {
  sum(this: number[]): number;
}

Notice how we used the this type which is a synthetic parameter does not change the arity of the function. The syntax you attempted to use, while an interesting guess, is used for another purpose namely type guards.

The interesting part is that the type annotation on this takes precedence over the type of the interface. You could declare a generic parameter as well, apply it to this, and place restrictions on T so it can be composed as well. There is a ton of flexibility.

Here's an interesting one that combines both the interface type and refines it with this

interface Array<T> {
  flatten(this: T[][]): T[];
}
like image 57
Aluan Haddad Avatar answered Dec 11 '25 22:12

Aluan Haddad



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!