如何在运行时向类中添加静态函数?

时间:2016-08-30 05:10:34

标签: typescript

我在下面的示例中编写了一个类装饰器可以工作):

function WrapIt(options) {
  return (klass: any) => {
    var newConstructor = function () {
      return new klass.apply(null, arguments);
    };
    newConstructor.prototype = klass.prototype;

    // THIS must work as a static function in the output class
    newConstructor.factory = (amount: number) => {
      var newObj;
      var list = [];
      for (var n=0; n<amount; n++) {
        newObj = new klass();
        newObj.name = '#' + n + ': ' + newObj.selector();
        list.push(newObj);
      }

      return list;
    };

    return newConstructor;

    // return <typeof klass> newConstructor;
    /* The way commented above shows these warnings:
    [default] /.../decorators.ts:16:24 
      Property 'factory' does not exist on type '() => any'.
    */
  }
}

@WrapIt({
  option1: 'yay'
})
class Dog {
  selector() {
    return 'a dog'
  }
}

@WrapIt({
  option1: 'yay'
})
class Cat {
  selector() {
    return 'a cat'
  }
}

您还可以在此处看到它:http://plnkr.co/edit/tAXMOt?p=preview

但是尽管它有效,TypeScript编译器坚持这些警告:

[default] /.../my-classes.ts:11:1 
  Unable to resolve signature of class decorator when called as an expression.
  Type '() => void' is not assignable to type 'void'.

[default] /.../decorators.ts:13:24 
  Property 'factory' does not exist on type '() => void'.

看到警告很烦人,所以,我做错了什么?如何让TS编译器满意?

1 个答案:

答案 0 :(得分:0)

这似乎正在起作用并编译好:

type DogConstructor = {
    new(): Dog;
};

function WrapIt(options) {
    return (klass: typeof Dog): DogConstructor => {
        var newConstructor = function () {
            return (klass.apply(null, arguments) as DogConstructor);
        } as any;
        newConstructor.prototype = klass.prototype;

        newConstructor.factory = (amount: number) => {
            var newObj;
            var list = [];
            for (var n = 0; n < amount; n++) {
                newObj = new klass();
                newObj.name = '#' + n + ': ' + newObj.selector();
                list.push(newObj);
            }

            return list;
        };

        return newConstructor;
    }
}

@WrapIt({
    option1: 'yay'
})
class Dog {
    selector() {
        return 'a dog'
    }
}

iText in Action

唯一需要的是将newConstructor转换为any