首页 > 解决方案 > 打字稿中工厂函数返回的类不检查打字

问题描述

我创建了一个模块工厂函数,它返回一个由@Module({}). 我的问题是,该类取决于函数参数providerTokenstrategy所以我不能将它移到函数之外。当我运行代码时,它工作得非常好,但是没有正确检查类型的forRootforRootAsync。事实上打字稿不会对此抛出任何错误。还有什么应该是我的函数的返回值。我已经把它放在这里any以避免错误。

这就是我使用该函数创建模块的方式

const TwitterAuthModule =
  createHybridAuthModule<TwitterAuthModuleOptions>(
    TWITTER_HYBRID_AUTH_OPTIONS,
    TwitterAuthStrategy
  );

模块创建者工厂

export function createHybridAuthModule<T>(
  providerToken: string,
  strategy: any
): any {
  @Module({})
  class NestHybridAuthModule {
    static forRoot(options: T): DynamicModule {
      return {
        module: NestHybridAuthModule,
        providers: [
          {
            provide: providerToken,
            useValue: options,
          },
          strategy,
        ],
      };
    }

    static forRootAsync(
      options: ModuleAsyncOptions<ModuleOptionsFactory<T>, T>
    ): DynamicModule {
      return {
        module: NestHybridAuthModule,
        providers: [...this.createAsyncProviders(options), strategy],
      };
    }

    private static createAsyncProviders(
      options: ModuleAsyncOptions<ModuleOptionsFactory<T>, T>
    ): Provider[] {
      if (options.useExisting || options.useFactory) {
        return [this.createAsyncOptionsProvider(options)];
      }
      const useClass = options.useClass as Type<ModuleOptionsFactory<T>>;
      return [
        this.createAsyncOptionsProvider(options),
        {
          provide: useClass,
          useClass,
        },
      ];
    }

    private static createAsyncOptionsProvider(
      options: ModuleAsyncOptions<ModuleOptionsFactory<T>, T>
    ): Provider {
      if (options.useFactory) {
        return {
          provide: providerToken,
          useFactory: options.useFactory,
          inject: options.inject || [],
        };
      }

      const inject = [
        (options.useClass || options.useExisting) as Type<
          ModuleOptionsFactory<T>
        >,
      ];

      return {
        provide: providerToken,
        useFactory: async (optionsFactory: ModuleOptionsFactory<T>) =>
          await optionsFactory.createModuleOptions(),
        inject,
      };
    }
  }

  return NestHybridAuthModule;
}

创建的模块的使用。永远不会检查 forRoot 的值的类型

@Module({
  imports: [
    TwitterAuthModule.forRoot({
      consumerKey: '********',
      consumerSecret: '******',
      callbackURL: '*******',
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

标签: javascripttypescriptnestjstypescript-generics

解决方案


typescript 不检查您的类型的原因是NestHybridAuthModule因为any函数createHybridAuthModule返回类型是any. 删除它并允许 typescript 推断返回类型。

如果--noImplicitReturns使用,您可以使用通用接口

编辑: 感谢您指出。
更正示例:

interface INestHybridAuthModule<T> {
    new(...args: any[]): any,
    forRoot(options: T): DynamicModule
}
export function createHybridAuthModule<T>(
    providerToken: string,
    strategy: any
): INestHybridAuthModule<T> {
    class NestHybridAuthModule {
        static forRoot(options: T): DynamicModule {
            // logic here
        }
    }
    return NestHybridAuthModule
}

原来的:

简化示例:

interface INestHybridAuthModule<T> {
    forRoot(options: T): DynamicModule
}
export function createHybridAuthModule<T>(
    providerToken: string,
    strategy: any
): new (...args: any[]) => INestHybridAuthModule<T> {
    class NestHybridAuthModule {
        forRoot(options: T): DynamicModule {
            // logic here
        }
    }
    return NestHybridAuthModule
}

推荐阅读