```ts
export function quarterSpin(grid: number[][], turns: number): number[][] {
  const n = grid.length;
  if (n === 0) return [[]];
  const m = grid[0].length;

  // Handle non-square grids by exchanging width and height for odd turns
  if ((turns % 4) !== 0 && n !== m) {
    [n, m] = [m, n];
    grid = transpose(grid);
  }

  turns %= 4;
  for (let t = 0; t < turns; t++) {
    grid = rotateGrid(grid);
  }

  // Handle non-square grids by reversing rows after rotation
  if ((turns % 2) !== 0 && n !== m) {
    grid = grid.map(row => row.reverse());
  }

  return grid;
}

function transpose(matrix: number[][]): number[][] {
  return matrix[0].map((_, i) => matrix.map(row => row[i]));
}

function rotateGrid(grid: number[][]): number[][] {
  const n = grid.length;
  const rotated = Array.from({ length: n }, () => new Array(n).fill(0));
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      rotated[n - 1 - j][i] = grid[i][j];
    }
  }
  return rotated;
}
```