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

Posted

技术标签:

【中文标题】如何使用 Typescript 使用自定义方法实现类数组类?【英文标题】:How to implement array-like class with custom methods with Typescript? 【发布时间】:2016-09-06 15:29:27 【问题描述】:

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

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

我是这样看的:

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

打字稿可以吗?我寻找解决方案,但没有找到更接近这些要求的东西。谢谢!

【问题讨论】:

有什么问题?有什么不工作吗? 【参考方案1】:

您可以扩展 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&lt;any&gt;

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

【讨论】:

谢谢你的回复,我昨天也来到了这个方法。它似乎对我有用【参考方案2】:

似乎在 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 的自定义方法就不存在了。

【讨论】:

这似乎已经过时或错误,因为当我尝试您链接的文章中给出的代码时,它可以顺利运行,包括编译的 JavaScript jsfiddle.net/ub4Locdr

以上是关于如何使用 Typescript 使用自定义方法实现类数组类?的主要内容,如果未能解决你的问题,请参考以下文章

使用 TypeScript,React,ANTLR 和 Monaco Editor 创建一个自定义 Web 编辑器

如何在 TypeScript 中使用 Apollo Client 自定义钩子?

如何使用 TypeScript 导入自定义 node.js 插件模块

如何测试使用自定义 TypeScript React Hook 的组件?

如何使用 Material UI 和 TypeScript 将自定义道具传递给样式化组件?

如何将 TypeScript 与 withRouter、connect、React.Component 和自定义属性一起使用?