UNPKG

@thomzz/async-data

Version:

A lightweight, dependency-free utility for managing and typing asynchronous data states.

88 lines (87 loc) 3.56 kB
import { Override } from './utils/types'; /** * Represents the state of any asynchronous data, including loading, fulfilled, and rejected states. */ export type AsyncData<TData = unknown, TError = Error> = { isLoading: boolean; } & ({ state: 'pending'; data?: TData; } | { state: 'fulfilled'; data: TData; } | { state: 'rejected'; data?: TData; error: TError; }); /** * Narrows down the AsyncData type to the pending state. */ export type PendingAsyncData<TData = unknown, T extends AsyncData<TData> = AsyncData<TData>> = Extract<T, { state: 'pending'; }>; /** * Narrows down the AsyncData type to the fulfilled state. */ export type FulfilledAsyncData<TData = unknown, T extends AsyncData<TData> = AsyncData<TData>> = Extract<T, { state: 'fulfilled'; }>; /** * Narrows down the AsyncData type to the rejected state. */ export type RejectedAsyncData<TData = unknown, TError = Error, T extends AsyncData<TData, TError> = AsyncData<TData, TError>> = Extract<T, { state: 'rejected'; }>; export declare namespace AsyncData { /** * Creates a pending AsyncData object. */ function create<TData = unknown>(data?: TData, isLoading?: boolean): Extract<AsyncData<TData>, { state: 'pending'; }>; /** * Creates a fulfilled AsyncData object. */ function resolve<TData = unknown>(data: TData): FulfilledAsyncData<TData>; /** * Creates a rejected AsyncData object. */ function reject<TData = unknown, TError = Error>(data: TData | undefined, error: TError): RejectedAsyncData<TData, TError>; /** * Checks if the AsyncData is in the pending state. */ function isPending<TData = unknown, T extends AsyncData<TData> = AsyncData<TData>>(data: T): data is PendingAsyncData<TData, T>; /** * Checks if the AsyncData is in the fulfilled state. */ function isFulfilled<TData = unknown, T extends AsyncData<TData> = AsyncData<TData>>(data?: T): data is FulfilledAsyncData<TData, T>; /** * Checks if the AsyncData is fulfilled and the data is defined. */ function isFulfilledAndDefined<TData = unknown, T extends AsyncData<TData> = AsyncData<TData>>(data?: T): data is Extract<T, { state: 'fulfilled'; }> & { data: NonNullable<unknown>; }; /** * Checks if the AsyncData is in the rejected state. */ function isRejected<TData = unknown, TError = Error, T extends AsyncData<TData, TError> = AsyncData<TData, TError>>(data: T): data is RejectedAsyncData<TData, TError, T>; /** * Checks if an object is an AsyncData object. */ function is<TData = unknown, TError = Error>(object: object): object is AsyncData<TData, TError>; /** * Forks an AsyncData object, replacing its data while preserving its state. * This is particularly useful when you want to maintain the entire state of an AsyncData object, * but need to change the data it holds, for example, when transforming/selecting data for different usages. */ function fork<TData = unknown, TError = Error, TForkData = unknown, T extends AsyncData<TData, TError> = AsyncData<TData, TError>>(source: T, data: TForkData): T extends RejectedAsyncData<TData, TError> ? Override<RejectedAsyncData<TData, TError, T>, { data?: TForkData; }> : T extends PendingAsyncData<TData> ? Override<PendingAsyncData<TData, T>, { data?: TForkData; }> : T extends FulfilledAsyncData<TData> ? Override<FulfilledAsyncData<TData, T>, { data: TForkData; }> : never; }