```typescript
export function topologicalSort(nodes: readonly string[], edges: readonly (readonly [string, string])[]): string[] {
    const graph: { [node: string]: Set<string> } = {};
    const inDegree: { [node: string]: number } = {};

    nodes.forEach(node => {
        graph[node] = new Set();
        inDegree[node] = 0;
    });

    edges.forEach(([from, to]) => {
        if (!graph[from] || !graph[to]) throw new Error(`Node not found: ${from} or ${to}`);
        if (graph[from].has(to)) return; // Ignore duplicate edges
        graph[from].add(to);
        inDegree[to]++;
    });

    const queue = nodes.filter(node => inDegree[node] === 0);
    const result: string[] = [];

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

        for (const neighbor of graph[node]) {
            if ((inDegree[neighbor] -= 1) === 0) {
                queue.push(neighbor);
            }
        }
    }

    if (result.length !== nodes.length) throw new Error('Cycle detected');

    return result;
}
```