typescriptapplicativefantasyland

Is it possible to constrain generic classes for specific methods?


Let's say I create a container in TypeScript. It could be any container but I'll use the following simple example:

class Container<T> {
  val: T;
  constructor(t: T) {
    this.val = t;
  }
}

Say I'd like to offer a function so that if I have two containers with numbers in, I can easily create a new container with those numbers added together.

class Container<T> {
  val: T;
  constructor(t: T) {
    this.val = t;
  }
  add(c: Container<number>): Container<number> {
    return new Container(this.val + c.val);
  }
}

However I cannot figure out if it is possible to make the above code typecheck. The problem is that all I know about this.val is that it is of type T (which is nothing). I'd like to somehow constrain the add method so that it can only be invoked on instances of Container<T> where T == number. Is that possible in TypeScript?

The above is just a contrived example. What I actually want to do is to create a TypeScript interface for applicative functors. An applicative function has a method that for Container would look like this:

ap<A, B>(c: Container<A>): Container<B> {
  return new Container(this.val(c.val));
}

So in this case I would have to know that T == (a: A) => B. More generally I'd like to be able to define this interface:

interface Applicative<T> {
  ...
  ap: <A, B>(a: Applicative<A>) => Applicative<B> // where T == (a: A) => B
  ...
}

Is any of this possible?


Solution

  • You can't have a restriction for T that applies on a single method. You can only have them at class level.