Bal*_*an웃 30 javascript typescript
有没有办法从JS本机函数继承一个类?
例如,我有一个像这样的JS函数:
function Xarray()
{
Array.apply(this, arguments);
//some stuff for insert, add and remove notification
}
Xarray.prototype = new Array();
Run Code Online (Sandbox Code Playgroud)
我试图将它转换为Typescript但我失败了!!
export class Xarray implements Array {
}
Run Code Online (Sandbox Code Playgroud)
编译器要求我定义所有Array接口属性.我知道如果我需要这个Xarray.prototype = new Array();,我必须Array在TS中扩展.
如何在TS中扩展JS本机对象?
Dav*_*ret 41
从TypeScript 1.6开始,您可以扩展Array类型,请参阅TypeScript中的新增内容
这是一个例子:
class MyNewArray<T> extends Array<T> {
getFirst() {
return this[0];
}
}
var myArray = new MyNewArray<string>();
myArray.push("First Element");
console.log(myArray.getFirst()); // "First Element"
Run Code Online (Sandbox Code Playgroud)
如果您要发送到ES5或更低版本,请使用以下代码:
class MyNewArray<T> extends Array<T> {
constructor(...items: T[]) {
super(...items);
Object.setPrototypeOf(this, MyNewArray.prototype);
}
getFirst() {
return this[0];
}
}
Run Code Online (Sandbox Code Playgroud)
在这里阅读更多关于为什么这是必要的.
Raj*_*l 웃 12
我认为没有办法继承像Array这样的现有接口,
export class Xarray implements Array {
}
Run Code Online (Sandbox Code Playgroud)
您应该创建一个函数并使用其原型继承它.Typescript也会接受它类似于javascript.
function Xarray(...args: any[]): void; // required in TS 0.9.5
function Xarray()
{
Array.apply(this, arguments);
// some stuff for insert, add and remove notification
}
Xarray.prototype = new Array();
Run Code Online (Sandbox Code Playgroud)
更新:这个问题很好地讨论并在jqfaq.com上为此提供了最佳解决方案.
//a dummy class it to inherite array.
class XArray {
constructor() {
Array.apply(this, arguments);
return new Array();
}
// we need this, or TS will show an error,
//XArray["prototype"] = new Array(); will replace with native js arrray function
pop(): any { return "" };
push(val): number { return 0; };
length: number;
}
//Adding Arrray to XArray prototype chain.
XArray["prototype"] = new Array();
//our Class
class YArray extends XArray {
///Some stuff
}
var arr = new YArray();
//we can use the array prop here.
arr.push("one");
arr.push("two");
document.writeln("First Elemet in array : " + arr[0]);
document.writeln("</br>Array Lenght : " + arr.length);
Run Code Online (Sandbox Code Playgroud)
希望,这可能对你有所帮助!
是的,可以在TS中扩展本机JS对象,但是存在扩展内置类型(lib.d.ts中包含的类型)的问题,例如Array.阅读这篇文章以获得解决方法:http://typescript.codeplex.com/workitem/4
因此,可以通过以下方式定义在稍后阶段扩展本机类型对象的类型接口:
/// <reference path="lib.d.ts"/>
interface Array {
sort: (input: Array) => Array;
}
Run Code Online (Sandbox Code Playgroud)
使用具体示例,您可以对数组中的某些元素进行排序,这些元素在接口中定义排序函数,然后在对象上实现它.
class Math implements Array {
sort : (x: Array) => Array {
// sorting the array
}
}
var x = new Math();
x.sort([2,3,32,3]);
Run Code Online (Sandbox Code Playgroud)
在研究这个问题时,我偶然发现了Ben Nadel关于在保持原生括号表示功能的同时扩展JavaScript数组的优秀文章.在对如何将其成功转换为TypeScript的初步混淆之后,我创建了一个可以进行子类化的完全工作的Collection类.
它可以完成Array所能做的所有事情,包括用括号括起来,在循环结构中使用(for,while,forEach),map等.
主要实施点是
implements Array位用法示例:
var foo = new Foo({id : 1})
var c = new Collection();
c.add(foo)
c.length === 1; // => true
foo === c[0]; // => true
foo === c.find(1); // => true
Run Code Online (Sandbox Code Playgroud)
我把它作为一个要点提供,完成了测试和一个子类的示例实现,但我在这里提供完整的源代码:
/*
* Utility "class" extending Array with lookup functions
*
* Typescript conversion of Ben Nadel's Collection class.
* https://gist.github.com/fatso83/3773d4cb5f39128b3732
*
* @author Carl-Erik Kopseng
* @author Ben Nadel (javascript original)
*/
export interface Identifiable {
getId : () => any;
}
export class Collection<T extends Identifiable> implements Array<T> {
constructor(...initialItems:any[]) {
var collection = Object.create(Array.prototype);
Collection.init(collection, initialItems, Collection.prototype);
return collection;
}
static init(collection, initialItems:any[], prototype) {
Object.getOwnPropertyNames(prototype)
.forEach((prop) => {
if (prop === 'constructor') return;
Object.defineProperty(collection, prop, { value: prototype[prop] })
});
// If we don't redefine the property, the length property is suddenly enumerable!
// Failing to do this, this would fail: Object.keys([]) === Object.keys(new Collection() )
Object.defineProperty(collection, 'length', {
value: collection.length,
writable: true,
enumerable: false
});
var itemsToPush = initialItems;
if (Array.isArray(initialItems[0]) && initialItems.length === 1) {
itemsToPush = initialItems[0];
}
Array.prototype.push.apply(collection, itemsToPush);
return collection;
}
// Find an element by checking each element's getId() method
public find(id:any):T;
// Find an element using a lookup function that
// returns true when given the right element
public find(lookupFn:(e:T) => boolean):T ;
find(x:any) {
var res, comparitor;
if (typeof x === 'function') {
comparitor = x;
} else {
comparitor = (e) => {
return e.getId() === x;
}
}
res = [].filter.call(this, comparitor);
if (res.length) return res[0];
else return null;
}
// Add an element
add(value:T);
// Adds all ements in the array (flattens it)
add(arr:T[]);
add(arr:Collection<T>);
add(value) {
// Check to see if the item is an array or a subtype thereof
if (value instanceof Array) {
// Add each sub-item using default push() method.
Array.prototype.push.apply(this, value);
} else {
// Use the default push() method.
Array.prototype.push.call(this, value);
}
// Return this object reference for method chaining.
return this;
}
remove(elem:T):boolean;
remove(lookupFn:(e:T) => boolean):boolean ;
remove(x:any):boolean {
return !!this._remove(x);
}
/**
* @return the removed element if found, else null
*/
_remove(x:any):T {
var arr = this;
var index = -1;
if (typeof x === 'function') {
for (var i = 0, len = arr.length; i < len; i++) {
if (x(this[i])) {
index = i;
break;
}
}
} else {
index = arr.indexOf(x);
}
if (index === -1) {
return null;
}
else {
var res = arr.splice(index, 1);
return res.length ? res[0] : null;
}
}
// dummy declarations
// "massaged" the Array interface definitions in lib.d.ts to fit here
toString:()=> string;
toLocaleString:()=> string;
concat:<U extends T[]>(...items:U[])=> T[];
join:(separator?:string)=> string;
pop:()=> T;
push:(...items:T[])=> number;
reverse:()=> T[];
shift:()=> T;
slice:(start?:number, end?:number)=> T[];
sort:(compareFn?:(a:T, b:T) => number)=> T[];
splice:(start?:number, deleteCount?:number, ...items:T[])=> T[];
unshift:(...items:T[])=> number;
indexOf:(searchElement:T, fromIndex?:number)=> number;
lastIndexOf:(searchElement:T, fromIndex?:number)=> number;
every:(callbackfn:(value:T, index:number, array:T[]) => boolean, thisArg?:any)=> boolean;
some:(callbackfn:(value:T, index:number, array:T[]) => boolean, thisArg?:any)=> boolean;
forEach:(callbackfn:(value:T, index:number, array:T[]) => void, thisArg?:any)=> void;
map:<U>(callbackfn:(value:T, index:number, array:T[]) => U, thisArg?:any)=> U[];
filter:(callbackfn:(value:T, index:number, array:T[]) => boolean, thisArg?:any)=> T[];
reduce:<U>(callbackfn:(previousValue:U, currentValue:T, currentIndex:number, array:T[]) => U, initialValue:U)=> U;
reduceRight:<U>(callbackfn:(previousValue:U, currentValue:T, currentIndex:number, array:T[]) => U, initialValue:U)=> U;
length:number;
[n: number]: T;
}
Run Code Online (Sandbox Code Playgroud)
当然,不需要比特Identifiable,方法find和remove方法,但我提供它们,因为完全成熟的例子比没有任何方法的裸骨集合更有用.
| 归档时间: |
|
| 查看次数: |
27384 次 |
| 最近记录: |