export interface IRange { start: number end: number contains(num: number): boolean containsRange(other: IRange): boolean isContainedInRange(other: IRange): boolean strictlyContainsRange(other: IRange): boolean isStrictlyContainedInRange(other: IRange): boolean } export class Range implements IRange { constructor(public start: number, public end: number) { if (!isValidRange(start, end)) { throw new Error("INVALID RANGE") } } contains(num: number): boolean { return this.start <= num && this.end >= num } containsRange(other: IRange): boolean { return this.start <= other.start && this.end >= other.end } isContainedInRange(other: IRange): boolean { return other.containsRange(this) } strictlyContainsRange(other: IRange): boolean { return this.start < other.start && this.end > other.end } isStrictlyContainedInRange(other: IRange): boolean { return other.strictlyContainsRange(this) } } export function isValidRange(start: number, end: number): boolean { return !(start < 0 || end < start) }