Skip to content

Instantly share code, notes, and snippets.

@karol-majewski
Last active July 7, 2020 16:17
Show Gist options
  • Save karol-majewski/5359cfb74cc8f08e7459cb2e61261e01 to your computer and use it in GitHub Desktop.
Save karol-majewski/5359cfb74cc8f08e7459cb2e61261e01 to your computer and use it in GitHub Desktop.
Subclassing built-in JavaScript (objects such as Array) in TypeScript
/**
* Returns the index of the searched element. Returns -1 when no element is found.
*/
function binarySearch<T>(array: SortedArray<T>, item: T): number {
let [left, right] = [0, array.length - 1];
while (left <= right) {
let middle = Math.floor((left + right) / 2);
if (array[middle] === item) {
return middle;
}
if (array[middle] < item) {
left = middle + 1;
} else {
right = middle -1
}
}
return -1;
}
type Comparator<T> = (left: T, right: T) => Comparison;
enum Comparison {
LessThan = -1,
Equal = 0,
GreaterThan = 1,
}
/**
* We can't allow sorted arrays to be mutated (e.g. pushed to).
*/
interface SortedArray<T> extends ReadonlyArray<T> {
readonly brand: unique symbol;
}
interface SortedArrayConstructor {
new <T>(items: T[], comparator: Comparator<T>): SortedArray<T>;
}
const SortedArray: SortedArrayConstructor = class<T> extends Array<T> {
constructor(items: T[], comparator: Comparator<T>) {
super(...items.slice().sort(comparator));
}
}
@karol-majewski
Copy link
Author

karol-majewski commented Jul 7, 2020

Usage:

const comparator: Comparator<number> = (left, right) => {
  if (left === right) {
    return Comparison.Equal;
  } else if (left < right) {
    return Comparison.LessThan
  } else {
    return Comparison.GreaterThan
  }
}

binarySearch(new SortedArray([5, 1, 4, 9, Math.E], comparator), 4); 
binarySearch([5, 1, 4, 9, Math.E], 4); // ⛔️ Compile-time error (array is not a SortedArray)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment