通过对象类型联合将值传递给方法

时间:2018-12-21 15:48:49

标签: typescript api oop

我有一个用于处理数据的类,该数据可能来自不同的来源。我需要将数据应该从那里传递给源。所以,我想问,什么是正确的方法:

  • 创建已定义接口的对象,该对象可以扩展并且对开发人员来说可能更清楚- processDataA
  • 全部传递一个变量,并按变量类型检查源-更少的代码而不是那么复杂- processDataB

  • 使用方法的单独变量不是一种情况-我需要将此值通过许多类/选项传递给目标类

示例:

interface DataProviderSource {
   dataURL?: string;
   dataArchive?: ArrayBuffer;
}

processDataA(source: DataProviderSource) {
   if (source.dataURL) {
      ...
   } else if (source.dataArchive) {
      ...
   } else {
      ...
   }
}

processDataB(source: ArrayBuffer | string) {
   if (source instanceof ArrayBuffer) {
      ...
   } else if (typeof source === "string") {
      ...
   } else {
     ...
   }
}

1 个答案:

答案 0 :(得分:1)

要避免的一件事是拥有这样的弱接口

interface DataProviderSource {
   dataURL?: string;
   dataArchive?: ArrayBuffer;
}

因为-因为每个属性都是可选的-所以它允许传递一个空对象。我们不希望那样—我们只希望传递一种格式的数据。

这是一个品味问题。一种方法是:

class Processor {
  static fromArrayBuffer(source: ArrayBuffer) {}
  static fromString(source: string) {}

  process(source: string | ArrayBuffer) {
    if (source instanceof ArrayBuffer) {
      return Processor.fromArrayBuffer(source);
    }

    return Processor.fromString(source);
  }
}

这很简单,但是它破坏了打开/关闭的原理。您还可以使用命名构造函数对源进行建模。在这种设计中,每种类型的信号源都配备有自己的处理器。

interface Source<T = any> {
    data: T;
    process: () => void;
}

class DataURL implements Source<string> {
    constructor(readonly data: string) {
        this.data = data;
    };

    process() {}
}

class Archieve implements Source<ArrayBuffer> {
    constructor(readonly data: ArrayBuffer) {
        this.data = data;
    };

    process() {}
}

class SomeOther implements Source<string> {
    constructor(readonly data: string) {
        this.data = data;
    };

    process() {}
}

此解决方案可供扩展。唯一重要的是源代码实现Source接口。

const process = (...sources: Source[]): void =>
  sources.forEach(source => source.process())

process(
    new DataURL('hello'),
    new Archieve(new ArrayBuffer(32)),
    new SomeOther('world')
);