【问题标题】:Typescript - factory pattern打字稿 - 工厂模式
【发布时间】:2020-01-03 21:27:06
【问题描述】:

我正在尝试为MainType 创建工厂。我还想重用已经创建的类型(实际上我需要相同的实例),所以我将它们存储在 ItemFactory 中。

class BaseType {

}

class MainType extends BaseType {

}

class ItemFactory {
    items: { [type: string]: BaseType } = {};

    get<T extends BaseType>(type: string): T | null {
        let item = this.items[type];

        if (!item) {
            switch (type) {
                case "main-type":
                    item = new MainType();
                    break;
                default:
                    return null;
            }

            this.items[type] = item;
        }

        return item as T;
    }
}

有没有办法简化通话

itemFactory.get<MainType>("main-type"); // current call

// option 1
const resolvedType = itemFactory.get<MainType>();

// option 2
const resolvedType = itemFactory.get("main-type");

我想要选项 1 或选项 2(两者都不需要),所以我不必同时传递标识符和类型来正确解析结果类型。

【问题讨论】:

    标签: typescript generics types type-conversion factory


    【解决方案1】:

    您需要在传递给itemFactory.get() 的名称和预期的输出类型之间为编译器提供某种映射。从名称到类型的映射是interfaces 最擅长的,因此您可以这样定义:

    interface NameMap {
      "main-type": MainType;
      // other name-type mappings here
    }
    

    然后你将 get() 方法更改为:

      get<K extends keyof NameMap>(type: K): NameMap[K] | null {
        let item = this.items[type];
    
        if (!item) {
          switch (type) {
            case "main-type":
              item = new MainType();
              break;
            default:
              return null;
          }
    
          this.items[type] = item;
        }
    
        return item as NameMap[K];
      }
    

    您将T extends BaseType 替换为NameMap[K],其中K extends keyof NameMap。现在以下(“选项 2”)将起作用:

    const resolvedType = itemFactory.get("main-type"); // MainType | null
    

    请注意,您将永远无法使用“选项 1”。 TypeScript 的类型系统在 JS 发出时得到erased,所以:

    itemFactory.get<MainType>();
    

    在运行时会变成这样:

    itemFactory.get();
    

    that 无法知道要返回什么,因为在代码开始运行之前,相关信息已被留下。这是故意的; not a goal of TypeScript 表示“在程序中添加或依赖运行时类型信息,或根据类型系统的结果发出不同的代码”。相反,TypeScript 应该“鼓励不需要运行时元数据的编程模式”......在这种情况下,这意味着使用像字符串 "main-type" 这样的运行时值而不是像 MainType 这样的设计时类型来跟踪get() 应该做什么。


    好的,希望对您有所帮助。祝你好运!

    Link to code

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-10
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多