Add type annotations to SortedArray

This commit is contained in:
Danila Fedorin 2021-09-29 19:52:35 -07:00
parent 7b2e452cd5
commit 3d2c74a760

View file

@ -18,18 +18,22 @@ import {BaseObservableList} from "./BaseObservableList";
import {sortedIndex} from "../../utils/sortedIndex.js"; import {sortedIndex} from "../../utils/sortedIndex.js";
import {findAndUpdateInArray} from "./common"; import {findAndUpdateInArray} from "./common";
export class SortedArray extends BaseObservableList { declare function sortedIndex<T>(array: T[], value: T, comparator: (left: T, right: T) => number): number;
constructor(comparator) {
export class SortedArray<T> extends BaseObservableList<T> {
private _comparator: (left: T, right: T) => number;
private _items: T[] = [];
constructor(comparator: (left: T, right: T) => number) {
super(); super();
this._comparator = comparator; this._comparator = comparator;
this._items = [];
} }
setManyUnsorted(items) { setManyUnsorted(items: T[]): void {
this.setManySorted(items); this.setManySorted(items);
} }
setManySorted(items) { setManySorted(items: T[]): void {
// TODO: we can make this way faster by only looking up the first and last key, // TODO: we can make this way faster by only looking up the first and last key,
// and merging whatever is inbetween with items // and merging whatever is inbetween with items
// if items is not sorted, 💩🌀 will follow! // if items is not sorted, 💩🌀 will follow!
@ -42,11 +46,11 @@ export class SortedArray extends BaseObservableList {
} }
} }
findAndUpdate(predicate, updater) { findAndUpdate(predicate: (value: T) => boolean, updater: (value: T) => any | false): boolean {
return findAndUpdateInArray(predicate, this._items, this, updater); return findAndUpdateInArray(predicate, this._items, this, updater);
} }
getAndUpdate(item, updater, updateParams = null) { getAndUpdate(item: T, updater: (existing: T, item: T) => any, updateParams: any = null): void {
const idx = this.indexOf(item); const idx = this.indexOf(item);
if (idx !== -1) { if (idx !== -1) {
const existingItem = this._items[idx]; const existingItem = this._items[idx];
@ -56,7 +60,7 @@ export class SortedArray extends BaseObservableList {
} }
} }
update(item, updateParams = null) { update(item: T, updateParams: any = null): void {
const idx = this.indexOf(item); const idx = this.indexOf(item);
if (idx !== -1) { if (idx !== -1) {
this._items[idx] = item; this._items[idx] = item;
@ -64,7 +68,7 @@ export class SortedArray extends BaseObservableList {
} }
} }
indexOf(item) { indexOf(item: T): number {
const idx = sortedIndex(this._items, item, this._comparator); const idx = sortedIndex(this._items, item, this._comparator);
if (idx < this._items.length && this._comparator(this._items[idx], item) === 0) { if (idx < this._items.length && this._comparator(this._items[idx], item) === 0) {
return idx; return idx;
@ -73,7 +77,7 @@ export class SortedArray extends BaseObservableList {
} }
} }
_getNext(item) { _getNext(item: T): T | undefined {
let idx = sortedIndex(this._items, item, this._comparator); let idx = sortedIndex(this._items, item, this._comparator);
while(idx < this._items.length && this._comparator(this._items[idx], item) <= 0) { while(idx < this._items.length && this._comparator(this._items[idx], item) <= 0) {
idx += 1; idx += 1;
@ -81,7 +85,7 @@ export class SortedArray extends BaseObservableList {
return this.get(idx); return this.get(idx);
} }
set(item, updateParams = null) { set(item: T, updateParams: any = null): void {
const idx = sortedIndex(this._items, item, this._comparator); const idx = sortedIndex(this._items, item, this._comparator);
if (idx >= this._items.length || this._comparator(this._items[idx], item) !== 0) { if (idx >= this._items.length || this._comparator(this._items[idx], item) !== 0) {
this._items.splice(idx, 0, item); this._items.splice(idx, 0, item);
@ -92,21 +96,21 @@ export class SortedArray extends BaseObservableList {
} }
} }
get(idx) { get(idx: number): T | undefined {
return this._items[idx]; return this._items[idx];
} }
remove(idx) { remove(idx: number): void {
const item = this._items[idx]; const item = this._items[idx];
this._items.splice(idx, 1); this._items.splice(idx, 1);
this.emitRemove(idx, item); this.emitRemove(idx, item);
} }
get array() { get array(): T[] {
return this._items; return this._items;
} }
get length() { get length(): number {
return this._items.length; return this._items.length;
} }
@ -116,8 +120,11 @@ export class SortedArray extends BaseObservableList {
} }
// iterator that works even if the current value is removed while iterating // iterator that works even if the current value is removed while iterating
class Iterator { class Iterator<T> {
constructor(sortedArray) { private _sortedArray: SortedArray<T> | null
private _current: T | null | undefined
constructor(sortedArray: SortedArray<T>) {
this._sortedArray = sortedArray; this._sortedArray = sortedArray;
this._current = null; this._current = null;
} }
@ -145,7 +152,7 @@ class Iterator {
export function tests() { export function tests() {
return { return {
"setManyUnsorted": assert => { "setManyUnsorted": assert => {
const sa = new SortedArray((a, b) => a.localeCompare(b)); const sa = new SortedArray<string>((a, b) => a.localeCompare(b));
sa.setManyUnsorted(["b", "a", "c"]); sa.setManyUnsorted(["b", "a", "c"]);
assert.equal(sa.length, 3); assert.equal(sa.length, 3);
assert.equal(sa.get(0), "a"); assert.equal(sa.get(0), "a");
@ -153,7 +160,7 @@ export function tests() {
assert.equal(sa.get(2), "c"); assert.equal(sa.get(2), "c");
}, },
"_getNext": assert => { "_getNext": assert => {
const sa = new SortedArray((a, b) => a.localeCompare(b)); const sa = new SortedArray<string>((a, b) => a.localeCompare(b));
sa.setManyUnsorted(["b", "a", "f"]); sa.setManyUnsorted(["b", "a", "f"]);
assert.equal(sa._getNext("a"), "b"); assert.equal(sa._getNext("a"), "b");
assert.equal(sa._getNext("b"), "f"); assert.equal(sa._getNext("b"), "f");
@ -162,7 +169,7 @@ export function tests() {
assert.equal(sa._getNext("f"), undefined); assert.equal(sa._getNext("f"), undefined);
}, },
"iterator with removals": assert => { "iterator with removals": assert => {
const queue = new SortedArray((a, b) => a.idx - b.idx); const queue = new SortedArray<{idx: number}>((a, b) => a.idx - b.idx);
queue.setManyUnsorted([{idx: 5}, {idx: 3}, {idx: 1}, {idx: 4}, {idx: 2}]); queue.setManyUnsorted([{idx: 5}, {idx: 3}, {idx: 1}, {idx: 4}, {idx: 2}]);
const it = queue[Symbol.iterator](); const it = queue[Symbol.iterator]();
assert.equal(it.next().value.idx, 1); assert.equal(it.next().value.idx, 1);