@equinor/fusion-observable
Version:
223 lines (207 loc) • 8.68 kB
text/typescript
export type TypeConstant = string;
/**
* Represents an action with a type property of type `T extends TypeConstant`.
* This type is commonly used in state management patterns like Redux to represent
* the actions that can be dispatched to update the application state.
*/
export type Action<T extends TypeConstant = TypeConstant> = { type: T };
/**
* An Action type which accepts any other properties.
* This is mainly for the use of the `Reducer` type.
* This is not part of `Action` itself to prevent types that extend `Action` from
* having an index signature.
*/
export interface AnyAction extends Action {
// Allows any extra properties to be defined in an action.
// biome-ignore lint/suspicious/noExplicitAny: This is a valid use case for an explicit `any` type
[extraProps: string]: any;
}
/**
* A function that creates an action of type `T extends Action = AnyAction`.
* The function can accept any number of arguments, which will be used to construct the action object.
*
* @param args - The arguments used to construct the action object.
* @returns An action of type `T`.
*/
// biome-ignore lint/suspicious/noExplicitAny: This is a valid use case for an explicit `any` type
export type ActionCreator<T extends Action = AnyAction> = (...args: any[]) => T;
/**
* Represents an asynchronous action creator function that can dispatch both a success and failure action.
*
* The `success` property is a required action creator that will be dispatched upon successful completion of the asynchronous operation.
* The `failure` property is an optional action creator that will be dispatched if the asynchronous operation fails.
*/
export type AsyncActionCreator = ActionCreator & {
success: ActionCreator;
failure?: ActionCreator;
};
/**
* Utility type that represents the possible action types for an asynchronous action creator.
*
* If the provided `AsyncActionCreator` type has a `failure` property that is an `ActionCreator`,
* the resulting type will be a union of the return types of the `AsyncActionCreator`, the `success`
* action creator, and the `failure` action creator.
*
* If the provided `AsyncActionCreator` type does not have a `failure` property that is an
* `ActionCreator`, the resulting type will be a union of the return types of the `AsyncActionCreator`
* and the `success` action creator.
*
* @template T - The type of the `AsyncActionCreator`.
*/
export type AsyncActionTypes<T> = T extends AsyncActionCreator
? T['failure'] extends ActionCreator
? ReturnType<T> | ReturnType<T['success']> | ReturnType<T['failure']>
: ReturnType<T> | ReturnType<T['success']>
: never;
/**
* Utility type that extracts the return type of an `ActionCreator` function, or returns the input type `T` if it is already an `AnyAction`.
* This is useful for ensuring the correct action type is used in reducers and other action-handling code.
*
* @template T - The action creator function or action type to extract the return type from.
* @returns The return type of the `ActionCreator` function, or the input type `T` if it is already an `AnyAction`.
*/
export type ActionInstance<T> = T extends ActionCreator
? ReturnType<T>
: T extends AnyAction
? T
: never;
/**
* Represents a map of action instances for a given set of action creators.
*
* @template T - The input type, which can be a record of action creators, or any other type.
*/
export type ActionInstanceMap<T> =
T extends Record<string, ActionCreator>
? {
[K in keyof T]: T[K] extends AsyncActionCreator
? AsyncActionTypes<T[K]>
: ActionInstance<T[K]>;
// [K in keyof T]: ActionInstance<T[K]>;
}
: {
[K in keyof T]: ActionInstanceMap<T[K]>;
};
/**
* Utility type that recursively extracts the `ActionTypes` from a given object type `T`.
*
* This type is useful for creating a union of all possible action types from a given set of actions.
*
* @param T - The object type to extract `ActionTypes` from.
* @returns The union of all `ActionTypes` from the given object type `T`.
*/
export type ActionTypes<T> =
T extends Record<string, ActionCreator>
? ActionTypes<ActionInstanceMap<T>>
: T extends Record<string, Action>
? T[keyof T]
: T extends Record<string, unknown>
? {
[K in keyof T]: ActionTypes<T[K]>;
}[keyof T]
: never;
/**
* An action with a string type and an associated payload. This is the
* type of action returned by `createAction()` action creators.
*
* @template P The type of the action's payload.
* @template T the type used for the action type.
* @template M The type of the action's meta (optional)
* @template E The type of the action's error (optional)
*
* @public
*/
export type PayloadAction<P = void, T extends string = string, M = never, E = never> = {
payload: P;
type: T;
} & ([M] extends [never]
? // biome-ignore lint/complexity/noBannedTypes: This is a valid use case for an empty object type
{}
: {
meta: M;
}) &
([E] extends [never]
? // biome-ignore lint/complexity/noBannedTypes: This is a valid use case for an empty object type
{}
: {
error: E;
});
/**
* Utility type that extracts the `type` property from an `Action` type.
*
* This type is useful when working with actions in a type-safe manner, as it allows you to
* get the specific type of an action without having to manually extract it.
*
* @template T - The action type or action creator to extract the `type` from.
* @returns The `type` property of the `Action` type, or `never` if the input type is not an `Action`.
*/
export type ActionType<T> = T extends ActionCreator
? ActionType<ActionInstance<T>>
: T extends Action
? T['type']
: never;
/**
* Extracts the action name from the action type string.
*
* The action type string is expected to be in the format `${actionName}::${actionSuffix}`.
* This function will return the `actionName` part of the string.
*
* If the action type string does not match the expected format, the entire action type string will be returned.
*
* @param TAction - The action type.
* @returns The action name extracted from the action type string.
*/
export type ActionBaseType<TAction extends Action> = TAction extends Action
? Extract<
// eslint-disable-next-line @typescript-eslint/no-unused-vars
TAction['type'] extends `${infer AName}::${infer ASuffix}` ? AName : TAction['type'],
string
>
: never;
/**
* Utility type that extracts the payload type from an `ActionInstance` type.
* If the `ActionInstance` extends `PayloadAction<any>`, the payload type is extracted.
* Otherwise, `never` is returned.
*
* This is useful for working with actions that have payloads, as it allows you to
* easily access the payload type without having to manually extract it.
*
* @template T - The `ActionInstance` type.
* @returns The payload type of the `ActionInstance`, or `never` if it does not extend `PayloadAction<any>`.
*/
export type ActionPayloadType<T> =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
ActionInstance<T> extends PayloadAction<any> ? ActionInstance<T>['payload'] : never;
/**
* Extracts an action type from a given action object type.
*
* This utility type is useful when you have a union of action objects, and you want to extract the action type for a specific action object.
*
* @template TAction - The action object type.
* @template TType - The action type constant. If not provided, it will be inferred from the `TAction` type.
* @returns The extracted action type.
*/
export type ExtractAction<
TAction extends Action,
TType extends TypeConstant = ActionType<TAction>,
> = Extract<TAction, Action<TType>>;
/**
* Utility type to extract action with a suffix from action type.
* The action type string is expected to be in the format `${actionName}::${actionSuffix}`.
*
* @template TAction - The action type to check.
* @template Suffix - The required suffix for the action type.
* @returns The original action type if it has the required suffix, or `never` if it does not.
*/
export type ActionWithSuffix<TAction extends Action, Suffix extends string> = TAction extends Action
? // eslint-disable-next-line @typescript-eslint/no-unused-vars
TAction['type'] extends `${infer AName}::${infer ASuffix}`
? ASuffix extends Suffix
? TAction
: never
: never
: never;
/**
* A record of named {@link ActionCreator} functions, used as input to
* {@link actionMapper} and {@link createState}.
*/
export type ActionDefinitions = Record<string, ActionCreator>;