19

我扩展了函数原型,但打字稿无法识别它。

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'

我如何扩展这个对象?

4

5 回答 5

33

标准打字稿库中有一个 Function 接口,它声明了 Function 对象的成员。您需要使用您自己的附加组件将 proc 声明为该接口的成员,如下所示:

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

需要从您打算使用“proc”的任何地方引用此接口。

于 2012-10-07T18:03:48.343 回答
14

像这样:

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

如果没有“声明全球”,它就行不通。

这就是模块增强在最近的 TypeScript 版本中的工作方式。查看文档并向下滚动到该Module augmentation部分。

于 2016-06-25T05:00:11.313 回答
1

静态方法

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;

非静态方法

declare global {
  interface Number {
    formatCurrency: () => string;
  }
}

Number.prototype.formatCurrency = function() : string {
  return '$' + this.toFixed(0).replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
}
于 2020-12-17T17:40:53.493 回答
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);
}

不幸的是,由于当前 TS的限制,它无法对您的 Symbols 进行类型检查,并且如果字符串由于某种原因与任何定义不匹配,它也不会对您大喊大叫,我会在查看它们是否已经存在后报告该错误知道的。

于 2019-03-26T02:25:54.607 回答
-1

我添加这个是为了建议不要像问题中所示的示例那样添加原型,因为很多人都查看这个问题。添加如下:

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

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

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

于 2017-05-02T22:52:41.617 回答