```ts
export function countTrails(rows: number, cols: number, blocked: number[][]): number {
  if (!Number.isInteger(rows) || !Number.isInteger(cols)) {
    throw new Error('rows and cols must be whole numbers');
  }

  const grid = Array.from({ length: rows }, () => Array(cols).fill(false));

  for (const [row, col] of blocked) {
    if (!Array.isArray(row) || row.length !== 2 || !Number.isInteger(row[0]) || !Number.isInteger(row[1])) {
      throw new Error('blocked must be a two-item list');
    }
    const [r, c] = row;
    if (r < 0 || r >= rows || c < 0 || c >= cols) {
      throw new Error('blocked cell outside the grid');
    }
    grid[r][c] = true;
  }

  if (grid[0][0] || grid[rows - 1][cols - 1]) {
    throw new Error('rope across the entrance or exit cell');
  }

  const directions = [[0, 1], [1, 0]];
  let count = 0;

  function dfs(row: number, col: number): void {
    if (row === rows - 1 && col === cols - 1) {
      count++;
      return;
    }
    for (const [dr, dc] of directions) {
      const newRow = row + dr;
      const newCol = col + dc;
      if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols && !grid[newRow][newCol]) {
        grid[newRow][newCol] = true;
        dfs(newRow, newCol);
        grid[newRow][newCol] = false;
      }
    }
  }

  dfs(0, 0);

  return count;
}
```