【问题标题】:Instantiate a dynamic loaded class in typescript?在打字稿中实例化一个动态加载的类?
【发布时间】:2021-12-29 15:23:28
【问题描述】:

我有一个抽象类设置如下:

export abstract class RuleValidator {
  public validate(condition: any, data: any) : boolean {
    return false;
  }
}

我编写了一个扩展类如下:

import { RuleValidator } from "./interfaces/ruleValidator";

export class WeightValidator extends RuleValidator {
  constructor() {
    super();
  }
  validate(condition: any, data: any) : boolean {
    console.log(JSON.stringify(condition));
    return true;
   }
   public test() {
     console.log('Test successful');
   }
}

我试图仅在验证规则时加载一个类(权重验证器)。 IE 我的规则集类似于{ "weight": { "gte": 2, "lt":9} }

在我的“引擎”中有以下代码:

export class RulesEngineService() {
  validators = {};
  private validate(rule: Rule, data: any){
    for (const requirement of rule.requirements) {
      for (const condition in requirement){
        let validator = this.getRuleValidator(condition);
        let result = validator.validate( requirement[condition], data)
      }
    }

  }

  private  getRuleValidator(validatorName: string): RuleValidator {
    validatorName = validatorName ? validatorName.toLocaleLowerCase() : validatorName;

    // populate only if validator doesn't exist
    if (typeof this.validators[ validatorName ] === 'undefined') {
      const Validator = require( '../ruleValidator/' + validatorName);
      const validator = new Validator();
      this.validators[validatorName] = validator;
      return null;
    }
    else {
      return this.validators[validatorName]
    }
  }
}

在过去,在 JavaScript 节点中,我可以简单地对包含类的文件执行请求,并使用 var Validator = require('/path/to/lib' + filename); validator = new Validator() 实例化它,如您在上面的调用中看到的那样。

我的问题是,当它尝试运行 validator = new Validator(); 代码行时,我收到一个错误 Validator is not a function。我看到 VSCode 调试器中的对象结构看起来像

   {
     WeightValidator: class WeightValidator.....
     __esModule:true
   }

我需要的是存储对我刚刚“需要”的类的实例的引用,并将其存储在我设置的对象中,并将该引用返回给调用方法。这样,我可以在该类中调用 validate 函数。我计划创建许多不同的验证器,它们将有自定义逻辑来完成验证工作。

我尝试了一些不同的想法,比如用类似这样的东西将负载包装在一个 Promise 中:

      const validator  = (async () => {
        let f = '../ruleValidator/' + validatorName;
        const v = await import(f);
        return v; 
      })().then(v => {
        const s = v.validate(condition, data)
        return s;
      });

我被告知 validate 方法不存在。另外,老实说,我还不需要它异步运行。我只是想在 TypeScript 中复制 JavaScript 所需的功能。

【问题讨论】:

    标签: typescript dynamic


    【解决方案1】:

    可以将类导出标记为default导出,在Typescript documentation中有说明:

    // 'weightValidator.ts'
    import { RuleValidator } from "./interfaces/ruleValidator";
    
    
    // use the `default` export
    export default class WeightValidator extends RuleValidator {
      
      //...
    
    }
    

    你应该可以使用它

    // 'ruleEngineService.ts'
    const Validator = require( '../ruleValidator/' + validatorName);
    const validator = new Validator();
    

    另一种方法可能是:

    // 'weightValidator.ts'
    import { RuleValidator } from "./interfaces/ruleValidator";
    
    export class WeightValidator extends RuleValidator {
      
      //...
    
    }
    
    // use a separate export which has the same name for all validators.
    export const sameExportNameForAllValidators = WeightValidator;
    

    然后:

    // 'ruleEngineService.ts'
    const Validator = require( '../ruleValidator/' + validatorName).sameExportNameForAllValidators;
    const validator = new Validator();
    

    【讨论】:

    • 使用第一个选项仍然给我“验证器不是构造函数”错误。当我尝试对两个类使用 const getValidator 时,尝试第二种方法给了我以下错误。 src/domain/ruleValidator/index.ts:2:1 - error TS2308: Module './postalCode' has already exported a member named 'getValidator'. Consider explicitly re-exporting to resolve the ambiguity. 2 export * from './weight';
    • 我的错误。尝试第二种方法确实有效。我最初认为这不是因为我最终想出了一个解决方案,但它要求我将每个类导出到 index.ts 文件中,然后将短名称(如 postalCode)转换为类名 PostalCodeValidator。
    猜你喜欢
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 1970-01-01
    • 2018-06-15
    • 2018-08-14
    • 1970-01-01
    • 2017-05-23
    相关资源
    最近更新 更多