typescript - 如何扩展 Array 类并保留其实现

标签 typescript class-extensions

我想向 Array 类添加一些函数(我不希望将它们作为类的外部函数,因为理想情况下在对象后面键入 . 时可以发现它们)。这是我目前所拥有的:

export class List<T> extends Array<T> {
    constructor(items?: Array<T>) {
        super(...items)
        Object.setPrototypeOf(this, List.prototype);
    }

    get first(): T {
        return this[0]
    }
}

这运行良好:

const list = new List([1,2,3]);
console.log(list.first)

但是如果我尝试运行这个:

const list = new List([1,2,3]);
console.log(list.map(x=>x*2))

我收到以下错误:

        super(...items)
        ^
TypeError: Found non-callable @@iterator

理想情况下,我会得到一个等效于 new List(this.map(x=>x*2)) 的对象。我如何扩展 Array 类而不必重写所有方法阵列?

最佳答案

我认为这里的问题是你的 List构造函数不期望与 Array 相同的参数构造函数。

当像 map() 这样的内置方法时创建一个新数组,他们使用在 static Symbol.species class property 中找到的构造函数构造它.默认情况下,这与类构造函数本身相同......除非您覆盖它。所以List[Symbol.species]List .和 List.prototype.map()最终会调用 new List(...) .我很确定这些方法需要 [Symbol.species] 处的构造函数采取the same arguments as the Array constructor ,即这些重载之一:

new Array(element0, element1[, ...[, elementN]]); // variadic arguments, one per item in array
new Array(arrayLength); // one numeric argument specifying length 

但是你的List构造函数期望处理它的第一个(也是唯一的)参数 items作为可迭代对象(因为它在对 super(...items) 的调用中使用了 spread syntax。当 list.map(x=>x*2) 执行时,它会调用类似于 new List(3) 的内容,并且您会收到有关 3 不可迭代的错误消息。


那么,您能做些什么来解决这个问题呢?到目前为止,最简单的方法是确保您的 List构造函数与 ArrayConstructor 兼容类型,让它采用相同的参数类型。

下一个最简单的事情是覆盖 List[Symbol.species]并返回 Array构造函数:

  static get [Symbol.species](): ArrayConstructor {
    return Array;
  }

但这意味着 list.map(x => x*2)返回 Array而不是 List .

假设您真的需要 List构造函数采用单个可迭代参数而不是与 Array 相同的可变参数或可能是单个数字参数,并假设您需要 list.map()返回 List ,您可以覆盖 List[Symbol.species]属性更复杂:

  static get [Symbol.species](): ArrayConstructor {
    return Object.assign(function (...items: any[]) {
      return new List(new Array(...items))
    }, List) as any;
  }

这实质上会导致 native 方法调用 new List(new Array(x,y,z))而不是 new List(x,y,z) .

好的,希望这有道理并能为您指明方向。祝你好运!

关于typescript - 如何扩展 Array 类并保留其实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54522949/

相关文章:

swift - 如何在 NSDate 中添加对 _Incrementable 的一致性

inheritance - 数据和开放式不兼容,我有哪些选择?

ios - ObjC - 为什么允许实例访问 .m 文件中的类扩展属性?

node.js - 如何验证yup中的枚举

typescript - typescript 中的 this 关键字。这是一个错误吗?

javascript - Angular 2 将数据传递到 for 循环中

ios - 尝试在单例中分配属性时出现 SIGABR 异常

javascript - 如何在 ionic 4 中使用 alertcontroller 返回 promise ?

reactjs - React - 如何使用 typescript 定义 Prop