取消打字稿工厂绑定返回联合类型?

时间:2018-07-02 09:37:39

标签: typescript inversifyjs

我正在使用Inverseify v4.13.0和Typescript,这两个都是我的新手。

我有一个Logger界面:

interface Logger {
  log(level: string, message: string, meta?: any): void;
}

一个TYPES文件:

const TYPES = {
  Config: Symbol.for('Config'),
  LoggerFactory: Symbol.for('Factory<Logger>')
};

和一些绑定,包括我有问题的记录器工厂绑定,该绑定也将config对象作为参数:

referenceContainer.bind<Config>(TYPES.Config).to(Config);

referenceContainer.bind<interfaces.Factory<Logger>>(TYPES.LoggerFactory).toFactory<Logger>(
  (context: interfaces.Context) => {
    return (options: PrefixedLoggerOptions = {}): Logger => {
      // return an object that implements Logger
      return PrefixedLoggerFactory(options);
    };
  });

然后我尝试使用记录器:

async function runApp() {
  const config = referenceContainer.get<Config>(TYPES.Config);
  const logger = referenceContainer.get<interfaces.Factory<Logger>>(TYPES.LoggerFactory)(config.loggerOptions);

  // **** error: logger has no 'log' property ****
  logger.log('info', 'am I a logger? nope!');

  // but this works
  (logger as Logger).log('info', 'am I a logger? yep!');
}

(async () => {
  await runApp();
})();

如果我尝试使用Logger而不进行投射,则会看到此错误:

error TS2339: Property 'log' does not exist on type 'Logger | ((...args: any[]) => Logger)'.
Property 'log' does not exist on type '(...args: any[]) => Logger'.

工厂似乎正在返回其自身的联合返回类型-工厂函数(奇怪的??)和记录器。

我检查了typedef,尽管我不知道如何工作,但这似乎是正确的。来自typedef:

type Factory<T> = (...args: any[]) => (((...args: any[]) => T) | T);

我对工厂使用inverseify错误吗?我该如何纠正?

1 个答案:

答案 0 :(得分:0)

我正在猜测为什么要以这种方式实现-允许在绑定时进行两次迭代。如果Factory不是联合类型,则将无法绑定以下内容:

context => (options) => (destination) => { ...destination based logger... }

但是,正如您刚刚指出的,如果您确定工厂不会返回闭包,则可以将其转换为所需的类型。您也可以在分配时做到这一点:

const logger: Logger = referenceContainer.get<interfaces.Factory<Logger>>(TYPES.LoggerFactory)(config.loggerOptions) as Logger;

此外,最好使用@inject装饰器。我认为,由于这是runApp函数,就像一个入口点,因此可以使用它。但是否则,为了获得良好的去耦和可测试性,我们应该使用装饰器。