通过扩展现有的创建新的Typescript数据类型

时间:2015-07-20 12:52:53

标签: arrays typescript

我想通过扩展现有的Array来创建新的数据类型。

以下是扩展程序的示例:

interface Array<T> {
    Count(): number;
}

Array.prototype.Count = function() {
    return this.length;
}

令我担心的是弄乱现有的数据类型。有没有办法创建一个新的数据类型,其新的数据类型是Array的扩展名?

让我们称之为List<T>。其中List是使用Array方法的Count()

我查看了Class List<T> extends Array<T>,但这不起作用。有什么建议吗?

更新2016-04

随着TypeScript的新更新,我又给了它一个镜头......

目前的实施:

class List<T> extends Array<T> {
    private _items: Array<T> = [];
    constructor(items: Array<T>) {
        super();
        this._items = items;
    }
    public where(filter: any, ...arg): Array<T> {
        return this._items.filter(item => filter(item, ...arg));
    }
}

以下作品:

 interface IItem {
        name: string
   }

   let items = Array<IItem> = [];

   // add few 'item's to items.    

   let list = new List<IItem>(items);
   let filter = (item: IItem, name: string) => { return item.name === name };
   let filteredList = list.where(filter, name);

想要让这个工作:

let list = List<IItem> = [];

// add few 'item's to items.    

let filter = (item: IItem, name: string) => { return item.name === name };
let filteredList = list.where(filter, name);

编译器错误:

[ts] Type 'undefined[]' is not assignable to type 'List<IItem>'.
Property '_items' is missing in type 'undefined[]'.
我错过了什么吗?

2 个答案:

答案 0 :(得分:2)

你现在可以用一种有点hacky的方式来做这件事,但是当你对原生类型进行子类化时,这会让你轻松地替换实现。

设置看起来像这样......

interface IList<T> extends Array<T> {
    count(): number;
}


var ListShim = function() {
    this.count = () => {
        return this.length;
    }
}
ListShim.prototype = new Array();

class List<T> {
    static create<T>() : IList<T> {
        return <IList<T>> new ListShim();
    }
}

你这样使用它:

var list = List.create<string>();

list.push('test a');
console.log(list.count());
console.log(list[0]);

list.push('test b');
console.log(list.count());
console.log(list[1]);

稍后,如果您发现可以对本机类型进行子类化(即所有浏览器都允许它),则可以在不更改调用代码的情况下替换实现。

interface IList<T> extends Array<T> {
    count(): number;
}

class List<T> extends Array<T> {
    static create<T>() : IList<T> {
        return new List();
    }

    count() {
        return this.length;
    }
}

这最后一个代码块是“在黑暗中刺伤”,因为我不知道这看起来会是什么样子,但是你应该通过create工厂方法与确切的细节隔离。

答案 1 :(得分:0)

ES2015(又名ES6 / Harmony)附带了内置类型的子类,但是现在没有浏览器默认启用该功能(参见compatibility table)。

你现在唯一的选择是使用一些原型黑客...