Можно ли ограничить универсальные классы для конкретных методов?

Допустим, я создаю контейнер в TypeScript. Это может быть любой контейнер, но я буду использовать следующий простой пример:

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

Скажем, я хотел бы предложить функцию, чтобы, если у меня было два контейнера с числами, я мог легко создать новый контейнер с этими числами, сложенными вместе.

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

Однако я не могу понять, можно ли выполнить приведенную выше проверку типов кода. Проблема в том, что все, что я знаю о this.val это то, что это типа T (что ничего). Я хотел бы как-то ограничить add метод, так что он может быть вызван только в случаях Container<T> где T == number, Это возможно в TypeScript?

Вышесказанное является лишь надуманным примером. На самом деле я хочу создать интерфейс TypeScript для аппликативных функторов. Аппликативная функция имеет метод, который для Container будет выглядеть так:

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

Так что в этом случае я должен был бы знать, что T == (a: A) => B, В целом, я хотел бы иметь возможность определить этот интерфейс:

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

Возможно ли это?

2 ответа

Решение

Вы не можете иметь ограничение для T, которое применяется к одному методу. Вы можете иметь их только на уровне класса.

Вы можете добавить ограничения к универсальным типам.

В вашем случае вы можете сделать что-то вроде этого:

interface HasNumber {
    x: number;
}

class Container<T extends HasNumber> {
}

Но вы не можете иметь ограничения, используя основные типы, такие как число, строка, Bool...

Другие вопросы по тегам