原型如何在打字稿上扩展?

时间:2012-10-07 04:27:35

标签: javascript typescript

我扩展了函数原型但是typescript无法识别它。

Function.prototype.proc = function() {
  var args, target, v;
  var __slice = [].slice;
  args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  target = this;
  while (v = args.shift()) {
    target = target(v);
  }
  return target;
};
// generated by coffee-script

var foo: (number) => (string) => number
  = (a) => (b) => a * b.length;
console.log(foo.proc("first", "second"))

结果:tsc -e

The property 'proc' does not exist on value of type 'Function'

如何扩展此对象?

5 个答案:

答案 0 :(得分:33)

标准typescript lib中有一个Function接口,用于声明Function对象的成员。您将需要将proc声明为该接口的成员,并使用您自己的add,如下所示:

interface Function {
    proc(...args: any[]): any;
}

此界面需要在您打算使用'proc'的任何地方引用。

答案 1 :(得分:11)

像这样:

declare global {
    interface Function {
        proc() : any;
    }
}

没有&#39;宣布全球&#39;它没有用。

在最近的TypeScript版本中,模块扩充的工作原理。查看documentation并向下滚动到Module augmentation部分。

答案 2 :(得分:1)

静态方法

static int distinctSubString(String S) {
    int count = (S.isEmpty()) ? 0 : 1;
    S = S.toLowerCase();
    HashSet<Character> letters = new HashSet<Character>();
    for (int i = 0; i < S.length(); i++) {
        if (letters.contains(S.charAt(i))) {
            letters.clear();
            count++;
        }
        letters.add(S.charAt(i));
    }
    return count;
}

非静态方法

declare global { 
  interface NumberConstructor {
    formatCurrency(num: number): string;
  }
}

export const formatCurrency = (num: number) => {
  if (!num) return '$0';
  return '$' + num.toFixed(0).replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
};

Number.formatCurrency = formatCurrency;

答案 3 :(得分:0)

我正在添加此内容以建议不要添加原型,如所示的示例,因为很多人都会查看此问题。添加如下:

interface Function {
    proc(...args: any[]): any;
}

Object.defineProperty(Function.prototype, 'proc', { value: function(arg: any[]) {
    // Your function body
}});

原因是如果直接将它添加到原型中,如果枚举了该函数的实例,则可以枚举它。 for i in ..。现在这个块可能在你无法控制的代码中(最近发生在我身上),所以最好保持代码尽可能安全。

答案 4 :(得分:0)

只需添加一下,如果您要添加定义已声明的内容,那么这就是这样做的类型安全方式,还可以防止错误的for in实现。

export const augment = <U extends (string|symbol), T extends {[key :string] :any}>(
    type  :new (...args :any[]) => T,
    name  :U,
    value :U extends string ? T[U] : any
) => {
    Object.defineProperty(type.prototype, name, {writable:true, enumerable:false, value});
};

可用于安全地填充。 示例

//IE doesn't have NodeList.forEach()
if (!NodeList.prototype.forEach) {
    //this errors, we forgot about index & thisArg!
    const broken = function(this :NodeList, func :(node :Node, list :NodeList) => void) {
        for (const node of this) {
            func(node, this);
        }
    };
    augment(NodeList, 'forEach', broken);

    //better!
    const fixed = function(this :NodeList, func :(node :Node, index :number, list :NodeList) => void, thisArg :any) {
        let index = 0;
        for (const node of this) {
            func.call(thisArg, node, index++, this);
        }
    };
    augment(NodeList, 'forEach', fixed);
}

不幸的是,由于limitation in current TS,它无法进行类型检查,并且如果字符串doesn't match any definition由于某种原因,它不会对您大喊大叫,我将在之后报告错误。看看他们是否已经知道。