```ts
export function hazardDetour(grid: number[][], start: number[], goal: number[]): number {
  if (!Array.isArray(grid) || grid.length === 0) {
    throw new Error("grid must be a non-empty array of rows");
  }
  const cols = Array.isArray(grid[0]) ? grid[0].length : 0;
  for (const row of grid) {
    if (!Array.isArray(row) || row.length !== cols || cols === 0) {
      throw new Error("grid rows must be equal-length non-empty arrays");
    }
    for (const cell of row) {
      if (cell !== 0 && cell !== 1) {
        throw new Error("cells must be 0 or 1");
      }
    }
  }
  const rows = grid.length;
  for (const point of [start, goal]) {
    if (
      !Array.isArray(point) ||
      point.length !== 2 ||
      !Number.isInteger(point[0]) ||
      !Number.isInteger(point[1]) ||
      point[0] < 0 ||
      point[0] >= rows ||
      point[1] < 0 ||
      point[1] >= cols
    ) {
      throw new Error("start and goal must be in-bounds [row, column] pairs");
    }
  }
  const unsafe = (r: number, c: number): boolean => grid[r][c] === 1;
  const isUnsafeOrAdjacent = (r: number, c: number): boolean => {
    if (unsafe(r, c)) return true;
    for (const [dr, dc] of [
      [-1, -1],
      [-1, 0],
      [-1, 1],
      [0, -1],
      [0, 1],
      [1, -1],
      [1, 0],
      [1, 1]
    ]) {
      const nr = r + dr;
      const nc = c + dc;
      if (nr >= 0 && nr < rows && nc >= 0 && nc < cols) {
        if (unsafe(nr, nc)) return true;
      }
    }
    return false;
  };
  if (isUnsafeOrAdjacent(start[0], start[1]) || isUnsafeOrAdjacent(goal[0], goal[1])) {
    return -1;
  }
  if (start[0] === goal[0] && start[1] === goal[1]) {
    return 0;
  }
  const seen = new Set<string>([start[0] + "," + start[1]]);
  const queue: number[][] = [[start[0], start[1], 0]];
  while (queue.length > 0) {
    const [r, c, steps] = queue.shift()!;
    for (const [dr, dc] of [
      [-1, 0],
      [1, 0],
      [0, -1],
      [0, 1]
    ]) {
      const nr = r + dr;
      const nc = c + dc;
      if (nr < 0 || nr >= rows || nc < 0 || nc >= cols) {
        continue;
      }
      if (isUnsafeOrAdjacent(nr, nc) || seen.has(nr + "," + nc)) {
        continue;
      }
      if (nr === goal[0] && nc === goal[1]) {
        return steps + 1;
      }
      seen.add(nr + "," + nc);
      queue.push([nr, nc, steps + 1]);
    }
  }
  return -1;
}
```