```ts
export function topoOrder(n: number, edges: [number, number][]): number[] {
  if (n <= 0) return [];

  const inDegree = Array.from({ length: n }, () => 0);
  const adjacencyList: Map<number, Set<number>> = new Map();

  // Build the graph
  for (const [u, v] of edges) {
    if (u < 0 || u >= n || v < 0 || v >= n) {
      throw new Error("Edge endpoints must be integers in the range 0 to n-1.");
    }
    adjacencyList.set(u, (adjacencyList.get(u) || new Set()).add(v));
    inDegree[v]++;
  }

  // Initialize queue with nodes having no incoming edges
  const queue: number[] = [];
  for (let i = 0; i < n; i++) {
    if (inDegree[i] === 0) {
      queue.push(i);
    }
  }

  const result: number[] = [];

  while (queue.length > 0) {
    const node = queue.shift()!;
    result.push(node);

    // Decrease in-degree of adjacent nodes
    for (const neighbor of adjacencyList.get(node) || []) {
      inDegree[neighbor]--;
      if (inDegree[neighbor] === 0) {
        queue.push(neighbor);
      }
    }
  }

  return result;
}
```