diff --git a/types/semaphore/index.d.ts b/types/semaphore/index.d.ts index 0fe1e2e5645201..7fa0d829bf1205 100644 --- a/types/semaphore/index.d.ts +++ b/types/semaphore/index.d.ts @@ -1,8 +1,17 @@ declare function semaphore(capacity?: number): semaphore.Semaphore; declare namespace semaphore { + /** + * Releases `n` (default `1`) units of capacity back to the semaphore. + */ + type Leave = (n?: number) => void; + interface Task { - (): void; + /** + * @param leave Releases the capacity held by this task. `take` passes it to every + * task it runs, so a task can release the semaphore without closing over it. + */ + (leave: Leave): void; } interface Semaphore { diff --git a/types/semaphore/semaphore-tests.ts b/types/semaphore/semaphore-tests.ts index 479853e5d1bab6..ab3b24fc2cdd2a 100644 --- a/types/semaphore/semaphore-tests.ts +++ b/types/semaphore/semaphore-tests.ts @@ -13,3 +13,16 @@ sem.leave(2); sem.current; const available: boolean = sem.available(2); + +// `take` passes `leave` to every task, so a task can release the semaphore +// without closing over it. Tasks that ignore it still type-check. +sem.take((leave: semaphore.Leave) => { + console.log("My task"); + leave(); +}); + +sem.take(2, (leave) => { + // $ExpectType Leave + leave; + leave(2); +});