Javascript 模仿TypeScript中的扩展方法

Javascript 模仿TypeScript中的扩展方法,javascript,typescript,extension-methods,Javascript,Typescript,Extension Methods,这是一个有趣的挑战。我正在用类似于C#的用法在TypeScript github to中阅读这一旧版本。有两种主要的方法被提出,一种是添加语法糖来扩展经常不受欢迎的对象原型,另一种是重写调用站点(参见优缺点) 我在想,也许我们可以用另一种方式,模仿同样适用于JavaScript的扩展方法 假设我们有以下功能: 函数includesAnyOf(数组:T[],…搜索元素:T[]){ 返回searchElements.some(=>array.includes()); } //例如: 常数a=[1,2

这是一个有趣的挑战。我正在用类似于C#的用法在TypeScript github to中阅读这一旧版本。有两种主要的方法被提出,一种是添加语法糖来扩展经常不受欢迎的对象原型,另一种是重写调用站点(参见优缺点)

我在想,也许我们可以用另一种方式,模仿同样适用于JavaScript的扩展方法

假设我们有以下功能:

函数includesAnyOf(数组:T[],…搜索元素:T[]){
返回searchElements.some(=>array.includes());
}
//例如:
常数a=[1,2,3];
常数b=3;
包括(a,b);//真的
//作为扩展方法,它看起来像:
//a.包括(b)项;
现在我想实现函数
ext
,这样我可以:

ext(a).includesAnyOf(b)

保留参数的所有类型。我不知道这是否可能,但我从这开始,不知道如何完成它

功能扩展(对象:任何){
返回{
includesAnyOf:(…args:any[])=>includesAnyOf(…??)
};
}

我认为这是一个有趣的挑战,你认为这是如何实现的,以及如何推广它,或者你能想出一个更好的方法吗?

我发现最简单的方法就是使用它来完成任务

function ext<T, E>(obj: T, extension: E) {
   return (receiver: (extended: T & E) => any) => {
      receiver(new Proxy(obj, {
        get(target, prop, receiver) {
          if(prop in extension)
             return extension[prop];
          return Reflect.get(...arguments);
        },
        // TODO has, set, etc. according to needs
      } as T & E));
   };
}

ext(a, { includesAnyOf })(a => {
 a.includesAnyOf("stuff");
});
函数includesAnyOf(数组:T[],…搜索元素:T[]){
返回searchElements.some(=>array.includes());
}
从“lodash”导入{partial};
常数a=[1,2,3];
常数b=3;
常数ext=(o)=>{
返回{
includesAnyOf:部分(includesAnyOf,o)
};
};
console.log(
ext(a).includesAnyOf(b)//真
);

我发现的最简单的方法是使用来执行

函数includesAnyOf(数组:T[],…搜索元素:T[]){
返回searchElements.some(=>array.includes());
}
从“lodash”导入{partial};
常数a=[1,2,3];
常数b=3;
常数ext=(o)=>{
返回{
includesAnyOf:部分(includesAnyOf,o)
};
};
console.log(
ext(a).includesAnyOf(b)//真
);


感谢您接受挑战!我的目标是有一个更可读的代码,但前提是它不破坏强键入和自动完成。你的答案似乎不起作用。对于
a.includesAnyOf(“2”)
它返回
false
@orad字符串不是强类型的数字,你在内部
a
上得到了自动完成,但是你必须键入
ext(a,{……方法})(a=>)
才能得到扩展,依我看那没有用你是对的,我错了,但它不能为我编译,我只能在浏览器中运行它。是的,语法仍然冗长,我同意它没有那么有用。感谢您接受挑战!我的目标是有一个更可读的代码,但前提是它不破坏强键入和自动完成。你的答案似乎不起作用。对于
a.includesAnyOf(“2”)
它返回
false
@orad字符串不是强类型的数字,你在内部
a
上得到了自动完成,但是你必须键入
ext(a,{……方法})(a=>)
才能得到扩展,依我看那没有用你是对的,我错了,但它不能为我编译,我只能在浏览器中运行它。是的,语法仍然冗长,我同意它没有那么有用。你可能会对管道操作符感兴趣-尽管它还处于非常早期的阶段。哇,这太强大了!谢谢分享!我不知道为什么您希望
ext(a)
成为函数而不是扩展对象。也就是说,为什么你想做
ext(a)(x=>x.includesAnyOf(1))
而不是仅仅做
(ext(a))。includesAnyOf(1)
?顺便说一句,我认为一个令人困惑的问题是,你想要的是比TS舒适地处理的更高的顺序类型,即使是它可以处理的。如果
includesAnyOf
专门处理具体类型
number[]
,您可能会使用通用扩展函数获得良好的强类型。但由于您可能希望它支持泛型
T
T[]
,这是更高的阶数,您可能会看到
未知[]
或其他过早解析的泛型。@jcalz回答您的第一个问题,我可能想得太多了!我基本上是在寻找最接近
a.includesAnyOf(b)
语法的路径,而无需扩展对象原型或克隆数组。因此,如果我们能做
ext(a)。includesAnyOf(b)
,那就更好了。你可能会对管道操作符感兴趣,尽管它还处于非常早期的阶段。哇,这太强大了!谢谢分享!我不知道为什么您希望
ext(a)
成为函数而不是扩展对象。也就是说,为什么你想做
ext(a)(x=>x.includesAnyOf(1))
而不是仅仅做
(ext(a))。includesAnyOf(1)
?顺便说一句,我认为一个令人困惑的问题是,你想要的是比TS舒适地处理的更高的顺序类型,即使是它可以处理的。如果
includesAnyOf
专门处理具体类型
number[]
,您可能会使用通用扩展函数获得良好的强类型。但由于您可能希望它支持泛型
T
T[]
,这是更高的阶数,您可能会看到
未知[]
或其他过早解析的泛型。@jcalz回答您的第一个问题,我可能想得太多了!我基本上是在寻找最接近
a.includesAnyOf(b)
语法的路径,而无需扩展对象原型或克隆数组。因此,如果我们能做
ext(a)。includesAnyOf(b)
,那就更好了。
function ext<T, E>(obj: T, extension: E) {
   return (receiver: (extended: T & E) => any) => {
      receiver(new Proxy(obj, {
        get(target, prop, receiver) {
          if(prop in extension)
             return extension[prop];
          return Reflect.get(...arguments);
        },
        // TODO has, set, etc. according to needs
      } as T & E));
   };
}

ext(a, { includesAnyOf })(a => {
 a.includesAnyOf("stuff");
});