如何将变量参数传递给基类

时间:2014-12-30 16:36:05

标签: typescript

我想在基类构造函数中使用变量参数。派生类中的内容相同。构造函数可以接收未知数量的参数,我想将它们传递给基类构造函数,以进行一些处理。我没有找到任何好的解决方案,看起来这可以通过spread operator来解决,显然在TypeScript中不存在。它将被开发in version 1.5(我是对的吗?):

class TSBase{
  constructor(...args: any[]){
    //do stuff with args
  }
}

class TSSomeController extends TSBase{
  constructor(...args: any[]){         
    //let base do some stuff
    //super(...args); //this doesn't work, but it would be cool... :)
  }
}

在TypeScript中执行此操作的最佳方法是什么?我可以使用类似super.prototype.apply的内容吗?

3 个答案:

答案 0 :(得分:4)

如您所知,传播运营商尚未推出。

编辑 - 旁注:实际上,它现在可以在TypeScript 1.5中使用。只需super(...args);

关于在TypeScript 1.5之前执行此操作的最佳方法......这实际上取决于,但这里的一个解决方案并不涉及更改任何派生类并保持与您的内容相同。我想要这样做:

class TSBase {
  constructor(...args: any[]) {
    if (this.constructor != TSBase && args.length === 1 && args[0] instanceof Array) {
      args = args[0];
    }

    // work with args here... for example:
    args.forEach((val) => console.log(val));
  }
}

class TSSomeController extends TSBase{
  constructor(...args: any[]){         
    super(args);
  }
}

new TSBase(3, 4);                 // 3, 4
new TSBase([3, 4]);               // Array[2]
new TSSomeController(3, 4);       // 3, 4
new TSSomeController([3, 4]);     // Array[2]
new TSSomeController([3, 4], 5);  // Array[2], 5

基本上,你可以在基础构造函数中添加一个检查,使args数组仅在从派生类传入时,当有一个参数时,以及当该参数是数组时,等于第一个元素

答案 1 :(得分:2)

在许多情况下,inherited检查有帮助。这是其中之一:

class TSBase { 
  constructor( ...args: any[] ) {
    if ( this.constructor != TSBase ) args = args[0];

    //do stuff with args    
    console.log(args);
  }
}

class TSSomeController extends TSBase {  
  constructor( ...args: any[] ) {
    super(args);
  }
}


var base = new TSBase(1,2,3); // [1,2,3]
var child = new TSSomeController(1,2,3); // [1,2,3]

答案 2 :(得分:0)

您可以使用重载的构造函数来实现此目的:

具有超载/类型防护

class TSBase{
  constructor(args: any[]);
  constructor(...args: any[]);
  constructor(...args: any[]) {
    if (Array.isArray(args[0])) {
        args = args[0];
    }

    // Do stuff
  }
}

class TSSomeController extends TSBase{
  constructor(...args: any[]){         
    super(args);
  }
}

虽然看起来重复了constructor(...args: any[]),但值得记住的是你无法直接调用实现签名,因此你必须将它列为重载选项。

如果你打算传递一个数组数组,这个例子需要调整,因为它会破坏测试中使用的逻辑 - 但我认为你想要真正传递一个类型化的数组,例如string[]MyType[],而不是any[]

没有超载/类型防护

您也可以在没有过载和类型保护的情况下实现此目的:

class TSBase{
    protected args: any[];

    constructor(...args: any[]){
        this.args = args;
    }

    getArgs() {
        return this.args;
    }
}

class TSSomeController extends TSBase{
    constructor(...args: any[]){  
        super(null);
        this.args = args;    
    }
}

var a = new TSBase(1, 2, 3);
console.log(a.getArgs());

var b = new TSSomeController(4, 5, 6);
console.log(b.getArgs());