Подпись метода на основе предыдущего вызова метода - PullRequest
1 голос
/ 26 мая 2020

Мне нужно запрограммировать преобразование значений на основе различных шагов. Чтобы повторно использовать шаги, была предложена архитектура, в которой шаги могут быть переданы в преобразование, аналогично этому коду (например, для прописывания длинной строки и ее усечения после 13 символов):

Transformation.from("This is a long story").step(Uppercase).step(Truncate);

class Uppercase {
  public run(str: string): string {
    return str.toUpperCase();
  }
}

class Truncate {
  public run(str: string): string {
    return str.substr(0, 10) + '...';
  }
}

Is есть способ убедиться (желательно во время компиляции), что шаги совместимы друг с другом, т.е. что вывод одного шага совместим по типу с вводом следующего, поэтому следующий класс не разрешен после шага создание строки:

class SquareRoot {
  public run(num: number): number {
    return Math.sqrt(num);
  }
}

Достижение этого во время выполнения кажется возможным, если добавить два члена inputType и outputType к шагам и сравнить их, но я хотел бы выполнить проверку во время компиляции .

1 Ответ

2 голосов
/ 26 мая 2020

Сначала давайте определим класс Transformer.

class Transformation<T> {
  constructor(readonly value: T) {
    this.value = value;
  }

  public static from<U>(input: U): Transformation<U> {
    return new Transformation(input);
  }

  public step<U>(transformer: Transformer<T, U>): Transformation<U> {
    return new Transformation(transformer.run(this.value));
  }
}

Он использует интерфейс Transformer. Мы можем определить его как:

interface Transformer<T, U> {
  run(input: T): U;
}

При наличии этого преобразования гарантированно будут правильными во время компиляции.

Transformation.from("This is a long story")
  .step(new Uppercase())
  .step(new Truncate()); // OK

Transformation.from("This is a long story")
  .step(new Uppercase())
  .step(new SquareRoot()); // Compile-time error: Type 'string' is not assignable to type 'number'.ts(2345)

Обновление

Примечание: в вашем примере вы передаете конструкторы из Uppercase и Truncate в качестве step s. В моем решении вместо них используются экземпляры . Если вместо этого вы настаиваете на передаче конструкторов, вам нужно будет сделать метод run stati c.

class Uppercase {
  public static run(str: string): string {
    return str.toUpperCase();
  }
}

class Truncate {
  public static run(str: string): string {
    return str.substr(0, 10) + '...';
  }
}

class SquareRoot {
  public static run(num: number): number {
    return Math.sqrt(num);
  }
}

Transformation.from("This is a long story")
  .step(Uppercase)
  .step(Truncate);

Transformation.from("This is a long story")
  .step(Uppercase)
  .step(SquareRoot); // Compile-time error: Type 'string' is not assignable to type 'number'.ts(2345)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...