将函数参数限制为相同的键

虚伪的

我对打字稿很陌生,我正在尝试编写一些代码,这些代码从不同来源获取许多不同形状的数据,并将它们传递给将它们聚合的类(每个数据形状一个聚合器类)。

为此,我相信我需要一个函数(dispatch下面称为),它将采用通用类型的数据和该数据的聚合器类的标识符,但我正在努力限制参数足以让 typescript 满意。

这是我到目前为止:

enum SourceIdentifier {
  A = 'a',
  B = 'b'
}

interface DataA {
  prop1: number,
  prop2: number[],
}

interface DataB {
  prop3: number,
  prop4: number,
}

class BaseAggregator<Data> {
  public add(data: Data) {
    // Store the data to be aggregated.
  }
}

class AggregatorA extends BaseAggregator<DataA> {}
class AggregatorB extends BaseAggregator<DataB> {}

const managers = {
  [SourceIdentifier.A]: new AggregatorA(),
  [SourceIdentifier.B]: new AggregatorB()
}

// How to correctly constrain this function?
const dispatch = (data, source: SourceIdentifier) => {
  managers[source].add(data);
};

我试过使用泛型,但遇到打字稿错误:

const dispatch = <Data, Manager extends BaseAggregator<Data>>(data: Data, source: SourceIdentifier) => {
  /*
   * Type 'AggregatorA | AggregatorB' is not assignable to type 'Manager'.
   *   'Manager' could be instantiated with an arbitrary type which could be unrelated to 'AggregatorA | AggregatorB'
   */
  const manager: Manager = managers[source];
  manager.add(data);
};

是否真的可以约束这样的函数,还是由于运行时不存在的类型而注定了我的命运?谢谢,任何帮助表示赞赏。

虚伪的

我已经设法通过使用像这样的鉴别器来实现我想要的:

enum SourceIdentifier {
  A = 'a',
  B = 'b'
}

interface DiscriminatedData {
  discriminator: SourceIdentifier;
}

interface DataA extends DiscriminatedData {
  discriminator: SourceIdentifier.A,
  prop1: number,
  prop2: number[],
}

interface DataB extends DiscriminatedData {
  discriminator: SourceIdentifier.B,
  prop3: number,
  prop4: number,
}

type DataMessage = DataA | DataB;

class BaseAggregator<Data> {
  public add(data: Data) {
    // Store the data to be aggregated.
  }
}

class AggregatorA extends BaseAggregator<DataA> {}
class AggregatorB extends BaseAggregator<DataB> {}

const managers = {
  [SourceIdentifier.A]: new AggregatorA(),
  [SourceIdentifier.B]: new AggregatorB()
}

const dispatch = (data: DataMessage) => {
  const manager: BaseAggregator<unknown> = managers[data.discriminator];
  manager.add(data);
};

// Example
dispatch({discriminator: SourceIdentifier.A, prop1: 2, prop2: [3, 3]})

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章