import { FunctionLike, IsUnknown } from "./base.mjs";

//#region src/async.d.ts
/**
 * Get the type of the value that a promise resolves to.
 *
 * @example
 * ```
 * import type {Awaited} from 'type-fest';
 *
 * const value: Awaited<Promise<string>> = 'foo';
 * ```
 */
type Awaitable<T> = T | PromiseLike<T>;
/**
 * A type that can be either a value or a function that returns a value.
 *
 * @example
 * ```
 * import type {Resolvable} from 'type-fest';
 *
 * const foo: Resolvable<string> = 'bar';
 * const bar: Resolvable<string> = () => 'baz';
 * ```
 */
type Resolvable<T> = Awaitable<T> | (() => Awaitable<T>);
/**
 * Create a function type with a return type of your choice and the same parameters as the given function type.
 *
 * Use-case: You want to define a wrapped function that returns something different while receiving the same parameters. For example, you might want to wrap a function that can throw an error into one that will return `undefined` instead.
 *
 * @example
 * ```
 * import type {SetReturnType} from 'type-fest';
 *
 * type MyFunctionThatCanThrow = (foo: SomeType, bar: unknown) => SomeOtherType;
 *
 * type MyWrappedFunction = SetReturnType<MyFunctionThatCanThrow, SomeOtherType | undefined>;
 * //=> type MyWrappedFunction = (foo: SomeType, bar: unknown) => SomeOtherType | undefined;
 * ```
 */
type SetReturnType<TFunct extends (...arguments_: any[]) => any, TypeToReturn> = TFunct extends ((this: infer ThisArgument, ...arguments_: infer Arguments) => any) ? IsUnknown<ThisArgument> extends true ? (...arguments_: Arguments) => TypeToReturn : (this: ThisArgument, ...arguments_: Arguments) => TypeToReturn : (...arguments_: Parameters<TFunct>) => TypeToReturn;
type AsyncFunction = (...arguments_: any[]) => Promise<unknown>;
/**
 * Unwrap the return type of a function that returns a `Promise`.
 *
 * There has been [discussion](https://github.com/microsoft/TypeScript/pull/35998) about implementing this type in TypeScript.
 *
 * @example
 * ```ts
 * import type {AsyncReturnType} from 'type-fest';
 * import {asyncFunction} from 'api';
 *
 * // This type resolves to the unwrapped return type of `asyncFunction`.
 * type Value = AsyncReturnType<typeof asyncFunction>;
 *
 * async function doSomething(value: Value) {}
 *
 * asyncFunction().then(value => doSomething(value));
 * ```
 */
type AsyncReturnType<Target extends AsyncFunction> = Awaited<ReturnType<Target>>;
/**
 * Create an async version of the given function type, by boxing the return type in `Promise` while keeping the same parameter types.
 *
 * Use-case: You have two functions, one synchronous and one asynchronous that do the same thing. Instead of having to duplicate the type definition, you can use `Asyncify` to reuse the synchronous type.
 *
 * @example
 * ```
 * import type {Asyncify} from 'type-fest';
 *
 * // Synchronous function.
 * function getFooSync(someArg: SomeType): Foo {
 *   // …
 * }
 *
 * type AsyncifiedFooGetter = Asyncify<typeof getFooSync>;
 * //=> type AsyncifiedFooGetter = (someArg: SomeType) => Promise<Foo>;
 *
 * // Same as `getFooSync` but asynchronous.
 * const getFooAsync: AsyncifiedFooGetter = (someArg) => {
 *   // TypeScript now knows that `someArg` is `SomeType` automatically.
 *   // It also knows that this function must return `Promise<Foo>`.
 *   // If you have `@typescript-eslint/promise-function-async` linter rule enabled, it will even report that "Functions that return promises must be async.".
 *
 *   // …
 * }
 * ```
 */
type Asyncify<TFunct extends FunctionLike> = SetReturnType<TFunct, Promise<Awaited<ReturnType<TFunct>>>>;
/**
 * Get the result type of a `Promise`
 *
 * @example
 * ```ts
 * import { Await } from '@stryke/types'
 *
 * const promise = new Promise<string>((res, rej) => res('x'))
 *
 * type test0 = C.Await<typeof promise>  // string
 * type test1 = C.Await<Promise<number>> // number
 * ```
 *
 * @param P - A promise
 * @returns [[Any]]
 */
type Await<P> = P extends Promise<infer A> ? A : P;
//#endregion
export { AsyncFunction, AsyncReturnType, Asyncify, Await, Awaitable, Resolvable, SetReturnType };
//# sourceMappingURL=async.d.mts.map