Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 基于先前方法调用的方法签名_Typescript - Fatal编程技术网

Typescript 基于先前方法调用的方法签名

Typescript 基于先前方法调用的方法签名,typescript,Typescript,我需要根据不同的步骤编写一个值转换程序。为了重用这些步骤,提出了一种架构,其中可以将这些步骤传递给转换,类似于此代码(例如,将长字符串大写并在13个字符后截断): 是否有办法确保(最好是在编译时)这些步骤彼此兼容,即一个步骤的输出与下一个步骤的输入类型兼容,因此在生成字符串的步骤之后不允许使用以下类: class SquareRoot { public run(num: number): number { return Math.sqrt(num); } } 通过将两个成员in

我需要根据不同的步骤编写一个值转换程序。为了重用这些步骤,提出了一种架构,其中可以将这些步骤传递给转换,类似于此代码(例如,将长字符串大写并在13个字符后截断):

是否有办法确保(最好是在编译时)这些步骤彼此兼容,即一个步骤的输出与下一个步骤的输入类型兼容,因此在生成字符串的步骤之后不允许使用以下类:

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

通过将两个成员
inputType
outputType
添加到步骤中并进行比较,在运行时实现这一点似乎是可能的,但我希望在编译时进行检查。

首先,让我们定义
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));
  }
}
有了它,就可以保证转换在编译时是正确的

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)
更新

注意:在您的示例中,您将
大写
截断
的构造函数作为
步骤
传递。在我的解决方案中,使用了实例。如果坚持要传递构造函数,则需要将
run
方法设置为静态

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)

很好的解决方案。我用一种非常相似的方法解决了它。您可以在stackblitz上看到它:在那里您可以看到不需要为step类创建静态方法。还可以使用
step(transformer:{new():T})
并在函数中实例化它。哇,太棒了。顺便说一句,实例工作得很好。构造函数是早期尝试的遗物,但决不是必需的。
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)
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)