```ts
export function regionTotals(grid: number[][], queries: number[][]): number[] {
  if (!Array.isArray(grid) || grid.length === 0) {
    throw new Error("grid must be a non-empty list of rows");
  }
  const width = Array.isArray(grid[0]) ? grid[0].length : 0;
  if (width === 0) {
    throw new Error("rows must be non-empty lists");
  }
  for (const row of grid) {
    if (!Array.isArray(row) || row.length !== width) {
      throw new Error("rows must all share one length");
    }
    for (const cell of row) {
      if (!Number.isInteger(cell)) {
        throw new Error("cells must be integers");
      }
    }
  }

  const prefixSum = Array.from({ length: grid.length + 1 }, () => 
    Array(width + 1).fill(0)
  );

  for (let i = 0; i < grid.length; i++) {
    for (let j = 0; j < width; j++) {
      prefixSum[i + 1][j + 1] = prefixSum[i][j + 1] + prefixSum[i + 1][j] - prefixSum[i][j] + grid[i][j];
    }
  }

  return queries.map(([top, left, bottom, right]) => {
    if (!Array.isArray(queries) || queries.length !== 4) {
      throw new Error("query must be a list of exactly four integers");
    }
    if (typeof top !== 'number' || typeof left !== 'number' || typeof bottom !== 'number' || typeof right !== 'number') {
      throw new Error("query values must be numbers");
    }
    if (top >= bottom || left >= right) {
      throw new Error("invalid query bounds");
    }
    if (top < 0 || top >= grid.length || left < 0 || left >= width || bottom > grid.length || right > width) {
      throw new Error("query reaches outside the grid");
    }

    return prefixSum[bottom][right] - prefixSum[top][right] - prefixSum[bottom][left] + prefixSum[top][left];
  });
}
```