That looks pretty good, yeah.
I'd suggest using the Task.sleep(for: .seconds...) but that looks okey.
In general we're interested in both deadlines (rather than timeouts) for tasks as well as such operations I think. Deadlines were blocked by not having time units in stdlib before, but now we could revisit the topic.
And a first() could be implemented with ... so it is for arbitrary amounts of child tasks as well.