【问题标题】:Return type in a factory method工厂方法中的返回类型
【发布时间】:2021-03-13 06:52:40
【问题描述】:

鉴于以下类层次结构,我是否以及如何将具体的处理程序实例类型映射到特定的事件类实例?

class Event {}

class EventA extends Event {
  constructor(public readonly value: number) {
    super();
  }
}

class EventB extends Event {
  constructor(public readonly message: string) {
    super();
  }
}

abstract class EventHandler<T> {
  public abstract run(): T;
}

class EventAHandler extends EventHandler<number> {
  constructor(private readonly event: EventA) {
    super();
  }

  public run() {
    return this.event.value + 1;
  }
}

class EventBHandler extends EventHandler<string> {
  constructor(private readonly event: EventB) {
    super();
  }

  public run() {
    return this.event.message + ' world!';
  }
}

class EventHandlerFactory {
  static createHandler<T extends Event>(event: T) {
    if (event instanceof EventA) {
      return new EventAHandler(event);
    }

    if (event instanceof EventB) {
      return new EventBHandler(event);
    }

    throw new Error('Not implemented!');
  }
}

const event = new EventA(1);

// T in createHandler is inferred as EventA
const handler = EventHandlerFactory.createHandler(event); // EventAHandler | EventBHandler

const result = handler.run(); // string | number -> should be number

Playground

我想要的是让handler 推断(或成为)EventAHandler 而不是联合类型(没有类型断言as),这样我就可以确定特定处理程序的结果类型。

【问题讨论】:

  • 您可以将createHandler 的返回类型设置为EventHandler&lt;T&gt;,但您需要在函数本身内部使用as
  • 很难知道您的事件处理程序 在构造之后会做什么,因为在您的示例中它们没有方法。作为一般的 OOP 思想,如果类型 AB 仅对实例化的目的很重要,并且您可以返回一般的 EventHandler 类型,则它并不关心它是 A 还是 B。但我不知道这在您的用例中是否有意义。
  • 这是我几天前回答的关于输入抽象工厂模式的类似问题。 stackoverflow.com/a/66501501/10431574 我在函数体中声明返回类型为EventHandler&lt;T&gt; 并带有一个断言。 (需要,因为 T 可能是 EventA | EventAEventA 以及一些额外的属性等)。
  • 当你只有两种类型时,你可以通过使用重载来避免很多问题,但这是不可扩展的。
  • @LindaPaiste 我已经更新了我的问题。重载似乎现在可以工作,但我想知道是否有更好的方法来做到这一点......

标签: typescript generics factory-pattern


【解决方案1】:

您可以使用条件类型来完成这项工作,但您必须进行一些转换:

type EventHandlerFromEvent<T extends Event> =
  T extends EventA ? EventAHandler : EventBHandler;

class EventHandlerFactory {
  static createHandler<T extends Event>(event: T): EventHandlerFromEvent<T> {
    if (event instanceof EventA) {
      return new EventAHandler(event) as EventHandlerFromEvent<T>;
    }

    if (event instanceof EventB) {
      return new EventBHandler(event) as EventHandlerFromEvent<T>;
    }

    throw new Error("Not implemented!");
  }
}

【讨论】:

    猜你喜欢
    • 2021-07-26
    • 2018-07-01
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多