如何使用Typescript自定义方法实现类似数组的类?

时间:2016-05-11 09:56:55

标签: javascript arrays class typescript iterable

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

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

    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!

2 个答案:

答案 0 :(得分:4)

您可以扩展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>

Examples

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

答案 1 :(得分:3)

在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);
  }

  ...
}

没有这些,自定义方法在运行时就不存在。