如何用Typescript用自定义方法实现类数组

How to implement array-like class with custom methods with Typescript?

本文关键字:实现 数组 自定义方法 何用 Typescript      更新时间:2023-09-26

我想实现一个类似数组的类:

  1. 接受数组作为构造函数的参数
  2. 应该是可迭代的,并且具有所有内置数组的方法
  3. 有一些自定义方法
  4. 应该能够扩展其他类

我是这样看的:

class BaseModel {
  arr: Array;
  constructor(arr: Array<any>) { // <= req. #1
    this.arr = arr;
  }
  serialize(arr) { // <= req. #3
    this.arr = arr;
  }
}
class ListModel extends BaseModel { // <= req. #4
  constructor(arr: Array<any>) { // <= req. #1
    super(arr);
  }
  sayHello() { // <= req. #3
    console.log('hello');
  }
}
let list = new ListModel([1,2,3]);
list.sayHello();
// expected output:
// 'hello'
list.push(4); // <= req. #2
for (let a of list) { // <= req. #2
  console.log(a);
}
// expected output:
// 1
// 2
// 3
// 4
list.serialize([2,3]);
for (let a of list) {
  console.log(a);
}
// expected output:
// 2
// 3

打字可能吗?我寻找解决方案,但没有找到更接近这些要求的解决方案。Thx!

您可以扩展Array类,并通过这样做来建立需求#2。
这里有一个我认为符合您所有要求的实现:

class MyArray<T> extends Array<T> {
    constructor(items?: T[]) {
        super();
        items && this.addItems(items);
    }
    public serialize(items: T[]): void {
        this.splice(0, this.length);
        this.addItems(items);
    }
    private addItems(items: T[]) {
        items.forEach(item => this.push(item));
    }
}
class StringsList extends MyArray<string> {
    public sayHello(): void { // req. #3
        console.log("hello");
    }
}
class NumbersList extends MyArray<number> {
    public sum(): number { // req. #3
        return this.reduce((prev: number, current: number) => prev + current);
    }
}

如果您不喜欢泛型部分,可以简单地扩展Array<any>

示例:

let arr1 = new MyArray(["hey", 4, true]);
console.log(arr1); // ["hey", 4, true]
arr1.push(99);
console.log(arr1); // ["hey", 4, true, 99]
arr1.forEach(item => console.log(item)); // hey, 4, true, 99
let arr2 = new StringsList(["str1", "str2"]);
console.log(arr2); // ["str1", "str2"]
arr2.serialize(["str3", "str4"]);
console.log(arr2); // ["str3", "str4"]
let arr3 = new NumbersList([1,2,3,4,5]);
console.log(arr3.sum()); // 15

在Typescript中,扩展数组似乎是不可能的,我遇到了运行时错误,我发现这篇优秀的文章以正确的方式做到了这一点:https://blog.simontest.net/extend-array-with-typescript-965cc1134b3

我们的自定义类实例需要像Singleton一样创建,以分配适当的原型,并且不要在运行时继承Array原型:

export class MyArray<T> extends Array<any> {
  static create<T>(): MyArray<T> {
    return Object.create(MyArray.prototype);
  }
  ...
}

如果没有这一点,JavaScript在运行时就不存在自定义方法。