Javascript 原型如何在typescript上扩展?

Javascript 原型如何在typescript上扩展?,javascript,typescript,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

我扩展了函数原型,但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"))

如何扩展此对象?

标准typescript库中有一个函数接口,用于声明函数对象的成员。您需要使用自己的加载项将proc声明为该接口的成员,如下所示:

interface Function {
    proc(...args: any[]): any;
}
此接口需要从您打算使用“proc”的任何地方引用。

如下:

declare global {
    interface Function {
        proc() : any;
    }
}
如果没有“声明全局”,它将不起作用


这就是模块扩充在最近的TypeScript版本中的工作方式。查看并向下滚动至
模块增强部分。

我添加此内容是为了建议不要添加类似问题中所示示例的原型,因为许多人都会看到此问题。添加如下:

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

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

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

如果您试图添加定义已经声明的内容,那么这是一种类型安全的方法,它还可以防止in实现中出现错误

export const augment=(
类型:new(…args:any[])=>T,
姓名:U,
值:U扩展字符串?T[U]:任意
) => {
defineProperty(type.prototype,name,{可写:true,可枚举:false,value});
};
可用于安全填充塑料。范例

//IE没有NodeList.forEach()
if(!NodeList.prototype.forEach){
//这个错误,我们忘记了索引和thisArg!
const breaked=函数(this:NodeList,func:(node:node,list:NodeList)=>void){
for(此节点的常量节点){
func(节点,this);
}
};
增加(节点列表“forEach”,已断开);
//更好!
const fixed=函数(this:NodeList,func:(node:node,index:number,list:NodeList)=>void,thisArg:any){
设指数=0;
for(此节点的常量节点){
函数调用(thisArg,node,index++,this);
}
};
增加(节点列表,“forEach”,固定);
}
不幸的是,由于出现了错误,它无法对您的符号进行打字检查,而且它也不会因为某种原因对您大喊大叫,我会在查看他们是否已经意识到错误后报告错误。

静态方法

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,');
}
非静态法

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,');
}

如何在自己的课堂上做到这一点?我希望你能解释为什么,但我确认,这里也一样。谢谢这就是模块扩充在最近的TypeScript版本中的工作方式。向下滚动:你没有进行任何类型检查(
defineProperty()
对你没有任何帮助),你需要@Hashbrown你读过问题了吗?这里没有类型检查,只是如何扩展现有的原型这是typescript,字面上就是使用该语言的全部意义。您添加的所有内容都应正确键入。我只是想,如果你要提醒人们有关枚举之类的事情,为什么不保持良好的实践,使用我们刚刚编写的接口呢(更不用说,任何人都会看到这些类型的问题,而不仅仅是提问者,因此采用最佳实践,而不仅仅是回答问题,就像你在这里添加自己的建议一样,这是一件好事)我同意你的观点,所有的东西都应该被输入,但是一些输入语法可能会有点令人生畏,让人们感到困惑,让他们错过了要点。