Created
November 30, 2017 04:55
-
-
Save felixfbecker/bc5a625c3e195132179199304e992476 to your computer and use it in GitHub Desktop.
Observable Array
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Subject } from 'rxjs/Subject' | |
export interface Splice<T> { | |
/** | |
* The zero-based location in the array from which to start removing elements. | |
*/ | |
start: number | |
/** | |
* The number of elements to remove. | |
*/ | |
deleteCount: number | |
/** | |
* Elements to insert into the array in place of the deleted elements. | |
*/ | |
items: ReadonlyArray<T> | |
} | |
const isReadonlyArray = (value: any): value is ReadonlyArray<any> => | |
value && typeof value === 'object' && typeof value.length === 'number' && typeof value.slice === 'function' | |
export const isObservableArray = (value: any): value is ObservableArray<any> => | |
value && | |
typeof value === 'object' && | |
typeof value.next === 'function' && | |
typeof value.splice === 'function' && | |
isReadonlyArray(value.elements) | |
export class ObservableArray<T> extends Subject<Splice<T>> { | |
public get elements(): ReadonlyArray<T> { | |
return this.mutatableElements | |
} | |
public set elements(elements: ReadonlyArray<T>) { | |
this.mutatableElements = Array.isArray(elements) ? elements : Array.from(elements) | |
this.next({ start: 0, deleteCount: Infinity, items: this.mutatableElements }) | |
} | |
private mutatableElements: T[] | |
constructor(elements: T[]) { | |
super() | |
this.elements = elements | |
this.mutatableElements = elements | |
} | |
/** | |
* Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements. | |
* @param start The zero-based location in the array from which to start removing elements. | |
* @param deleteCount The number of elements to remove. | |
*/ | |
public splice(start: number, deleteCount?: number): T[] | |
/** | |
* Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements. | |
* @param start The zero-based location in the array from which to start removing elements. | |
* @param deleteCount The number of elements to remove. | |
* @param items Elements to insert into the array in place of the deleted elements. | |
*/ | |
public splice(start: number, deleteCount: number, ...items: T[]): T[] | |
public splice(start: number, deleteCount = 0, ...items: T[]): T[] { | |
const deletedElements = this.mutatableElements.splice(start, deleteCount, ...items) | |
this.next({ start, deleteCount, items }) | |
return deletedElements | |
} | |
/** | |
* Removes the first element from an array and returns it. | |
*/ | |
public shift(): T | undefined { | |
const value = this.mutatableElements.shift() | |
this.next({ start: 0, deleteCount: 1, items: [] }) | |
return value | |
} | |
/** | |
* Inserts new elements at the start of an array. | |
* @param items Elements to insert at the start of the Array. | |
*/ | |
public unshift(...items: T[]): number { | |
const newLength = this.mutatableElements.unshift(...items) | |
this.next({ start: 0, deleteCount: 0, items }) | |
return newLength | |
} | |
/** | |
* Appends new elements to an array, and returns the new length of the array. | |
* @param items New elements of the Array. | |
*/ | |
public push(...items: T[]): number { | |
const newLength = this.mutatableElements.push(...items) | |
this.next({ start: Infinity, deleteCount: 0, items }) | |
return newLength | |
} | |
/** | |
* Removes the last element from an array and returns it. | |
*/ | |
public pop(): T | undefined { | |
const element = this.mutatableElements.pop() | |
this.next({ start: -1, deleteCount: 1, items: [] }) | |
return element | |
} | |
/** | |
* Reverses the elements in an Array. | |
*/ | |
public reverse(): this { | |
this.mutatableElements.reverse() | |
this.next({ start: 0, deleteCount: Infinity, items: this.mutatableElements }) | |
return this | |
} | |
/** | |
* Sorts an array. | |
* @param compareFn The name of the function used to determine the order of the elements. If omitted, the elements are sorted in ascending, ASCII character order. | |
*/ | |
public sort(compareFn?: (a: T, b: T) => number): this { | |
this.mutatableElements.sort(compareFn) | |
this.next({ start: 0, deleteCount: Infinity, items: this.mutatableElements }) | |
return this | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment