```typescript
/**
 * Merge overlapping intervals in ascending order.
 *
 * @param intervals - A list of pairs [start, end] representing intervals.
 * @returns The smallest list of non-overlapping pairs covering the same range,
 *          sorted ascending by start. Intervals that merely touch (end === next start) do merge.
 */
export function *mergeIntervals(intervals: number[][]): Generator<number[][]> {
    if (!intervals.length) return;

    const sorted = Array.from(intervals).sort((a, b) => a[0] - b[0]);
    const merged: number[][] = [sorted[0]];

    for (const current of sorted.slice(1)) {
        const last = merged[merged.length - 1];

        if (current[0] <= last[1]) {
            last[1] = Math.max(last[1], current[1]);
        } else {
            yield merged.pop();
            merged.push(current);
        }
    }

    for (const pair of merged) {
        if (pair[1] < pair[0]) {
            throw Error(`Invalid interval: [${pair[0]}, ${pair[1]}]`);
        }
        yield pair;
    }
}
```