@thomzz/async-data
Version:
A lightweight, dependency-free utility for managing and typing asynchronous data states.
88 lines (87 loc) • 3.56 kB
TypeScript
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;
}