/**
 * Channel is borrowed from Go.
 *
 * It doesn't have a notion of buffered; it's not for communication, just for scheduling.
 * Channels have infinite buffer space, however, you can use {@link Channel.push} to wait for a pushed value to be consumed.
 *
 * It's similar to but subtly different from a {@link AsyncGenerator}.
 * Whereas calling {@link AsyncGenerator.next} repeatedly creates a {@link Promise} of the next value, here, we instead wait for a value to be available before choosing to obtain it.
 * In this way it lends itself to "pull" semantics; the consumer of one or many {@link Channel} instances can decide how to proceed.
 */
export type Channel<T> = {
    /**
     * Push this value into the {@link Channel}.
     * Returns a {@link Promise} which resolves when it is consumed (optional).
     */
    push(t: T): Promise<void>;
    /**
     * Closes this channel.
     * No more values can be pushed, and the given value will be provided in perpetuity (i.e., will always be available).
     *
     * You must disambiguate T yourself to identify a closed channel.
     */
    close(t: T): void;
    /**
     * Waits until a value from this channel is available.
     *
     * This is as {@link ReadChannel.wait}, but with a wider type.
     */
    wait<V = Channel<T>>(value?: V): Promise<V>;
} & ReadChannel<T>;
export type ReadChannel<T> = {
    /**
     * Returns whether this channel is closed _and_ the close value has been provided via {@link ReadChannel.next}.
     *
     * This can be used to e.g., prematurely exit a loop or check what value was just retrieved.
     */
    readonly closed: boolean;
    /**
     * Waits until a value from this channel is available.
     *
     * Repeated calls to `wait()` will delay a microtask before resolving.
     * This allows a resolved task to safely consume a value synchronously after this resolves.
     *
     * For no other reason than convenience, this resolves with itself, unless you include another value as an argument.
     * The assumption is you can then synchronously consume the next value with {@link ReadChannel#next}.
     */
    wait<V = ReadChannel<T>>(value?: V): Promise<V>;
    /**
     * Returns whether {@link ReadChannel#next} has an available value.
     */
    pending(): boolean;
    /**
     * Consumes a value from this {@link ReadChannel}, if possible.
     * Otherwise, returns `undefined`.
     */
    next(): T | undefined;
};
type MessageType<Q> = Q extends ReadChannel<infer X> ? X : never;
export type SelectRequest = {
    [key: string | symbol]: ReadChannel<any> | undefined;
};
export type SelectResult<TChannels extends SelectRequest> = {
    [TKey in keyof TChannels]: Readonly<{
        key: TKey;
        ch: NonNullable<TChannels[TKey]>;
        m: MessageType<TChannels[TKey]>;
        closed: boolean;
    }>;
}[keyof TChannels];
export type ReadyResult<TChannels extends SelectRequest> = {
    [TKey in keyof TChannels]: Readonly<{
        key: TKey;
        ch: NonNullable<TChannels[TKey]>;
        closed: boolean;
    }>;
}[keyof TChannels];
/**
 * Waits for the first {@link Channel} that is ready based on key, reading that channel.
 * Returns with the key for matching.
 *
 * For safety, throws if no valid channels are passed (zero channels or all `undefined`).
 *
 * This uses JS' default object ordering for what is "first" when many are ready: integers >= 0 in order, all others, symbols.
 */
export declare function select<TChannels extends SelectRequest>(o: TChannels): Promise<SelectResult<TChannels>>;
/**
 * Waits for the first {@link Channel} that is ready based on key, reading that channel.
 * Returns with the key for matching.
 * Prefers the passed {@link AbortSignal}, which if aborted, returns `undefined`.
 *
 * Does not throw if missing channels, as the {@link AbortSignal} is an implied 'channel'.
 *
 * This uses JS' default object ordering for what is "first" when many are ready: integers >= 0 in order, all others, symbols.
 */
export declare function select<TChannels extends SelectRequest>(o: TChannels, signal: AbortSignal): Promise<SelectResult<TChannels> | undefined>;
export declare function select<TChannels extends SelectRequest>(o: TChannels): Promise<SelectResult<TChannels>>;
/**
 * Selects the first {@link ReadChannel} that is ready, reading that channel, or `undefined` if none are ready.
 * Returns with the key for matching.
 *
 * This uses JS' default object ordering for what is "first" when many are ready: integers >= 0 in order, all others, symbols.
 */
export declare function selectDefault<TChannels extends {
    [key: string | symbol]: ReadChannel<any> | undefined;
}>(o: TChannels): SelectResult<TChannels> | undefined;
/**
 * Selects the first {@link ReadChannel} that is ready, or `undefined` if none are ready.
 * Returns with the key for matching.
 *
 * This uses JS' default object ordering for what is "first" when many are ready: integers >= 0 in order, all others, symbols.
 */
export declare function readyDefault<TChannels extends {
    [key: string | symbol]: ReadChannel<any> | undefined;
}>(o: TChannels): ReadyResult<TChannels> | undefined;
/**
 * Builds a new {@link Channel}.
 */
export declare function newChannel<T>(): Channel<T>;
/**
 * Converts a {@link AbortSignal} into a channel which is closed when it aborts.
 */
export declare function channelForSignal<T = AbortSignal>(s: AbortSignal, v?: T): ReadChannel<T>;
/**
 * Converts a {@link AsyncGenerator} to a channel which contains {@link IteratorResult}.
 */
export declare function channelForGenerator<T, TReturn>(g: AsyncGenerator<T, TReturn, void>): ReadChannel<IteratorResult<T, TReturn>>;
export {};
