UNPKG

@ngxs/store

Version:
104 lines (94 loc) 5.11 kB
type _NoInfer<T> = T extends infer S ? S : never; /** * Blocks the ability of the typescript inferrence engine to be able to use the provided type as part of * inferring any type parameters from this usage. * @example * Primarily used to wrap parameters of functions in order to prevent the TypeScript inferrence engine * from inferring a type parameter of the function from the value provided to this parameter. * This essentially blocks the Contravariance of the function (through its parameters) so that the * function type parameter is purely determined by the Covariant requirements of the function's return type. * This is key to creating `StateOperator`s that are typed based on their contextual usage and not on the arguments * provided to them. This is critical for type safety and intellisense for State Operators. * Here is an example of how this benefits a state operator: * ```ts * declare function append<T>(items: NoInfer<T[]>): StateOperator<T[]>; * declare function appendBad<T>(items: T[]): StateOperator<T[]>; * * interface AAA { * foo?: boolean; * bar?: boolean; * } * * // Works * // (T in append is correctly inferred as AAA) * patch<{ test: AAA[] }>({ test: append([{ foo: true }]) }); * * // Incorrectly throws: Type 'AAA' is not assignable to type '{ foo: true; }'.ts(2322) * // (T in appendBad is incorrectly inferred as { foo: true; }) * patch<{ test: AAA[] }>({ test: appendBad([{ foo: true }]) }); * ``` * */ type NoInfer<T> = T extends (infer O)[] ? _NoInfer<O>[] : _NoInfer<T>; /** * IMPORTANT NOTE: This should not be used externally to the library, rather * the exported type `ExistingState<T>` should be used instead. * * Used to convert a type to its readonly form. This can be given any type, from * primitives to objects or arrays that could already be readonly or not. * This does not apply the readonly construct to nested objects, but only to the top level type. */ type ɵAsReadonly<T> = T extends Readonly<infer O> ? (O extends T ? Readonly<T> : T) : T; /** * Represents the existing state that is passed into a `StateOperator` which should * not be modified but will be used to build the new state returned by the `StateOperator`. */ type ExistingState<T> = T extends any ? ɵAsReadonly<T> : never; /** * This is a monotype unary function that is used to create a new state from an existing state. * A state operator is usually created by a function that is given some data * to integrate with the state and returns a state operator which integrates this data or instruction. * * In state management terminology this creator function is commonly referred to as a state operator * because it represents the operation to be performed. ie. `patch`, `append`, `insertItem`, `compose`, `iif`, etc. */ type StateOperator<T> = (existing: ExistingState<T>) => T; /** * @param items - Specific items to append to the end of an array */ declare function append<T>(items: NoInfer<T[]>): StateOperator<T[]>; declare function compose<T>(...operators: NoInfer<StateOperator<T>[]>): StateOperator<T>; type Predicate<T = any> = (value: T | Readonly<T>) => boolean; declare const isStateOperator: <T>(value: T | StateOperator<T>) => value is StateOperator<T>; declare const isPredicate: <T>(value: Predicate<T> | boolean | number) => value is Predicate<T>; /** * @param condition - Condition can be a plain boolean value or a function, * that returns boolean, also this function can take a value as an argument * to which this state operator applies * @param trueOperatorOrValue - Any value or a state operator * @param elseOperatorOrValue - Any value or a state operator */ declare function iif<T>(condition: NoInfer<Predicate<T>> | boolean, trueOperatorOrValue: NoInfer<StateOperator<T> | T>, elseOperatorOrValue?: NoInfer<StateOperator<T> | T>): StateOperator<T>; /** * @param value - Value to insert * @param [beforePosition] - Specified index to insert value before, optional */ declare function insertItem<T>(value: NoInfer<T>, beforePosition?: number): StateOperator<T[]>; type NotUndefined<T> = T extends undefined ? never : T; type ɵPatchSpec<T> = { [P in keyof T]?: T[P] | StateOperator<NotUndefined<T[P]>>; }; declare function patch<T extends Record<string, any>>(patchObject: NoInferPatchSpec<T>>): StateOperator<T>; /** * @param selector - Index of item in the array or a predicate function * that can be provided in `Array.prototype.findIndex` * @param operatorOrValue - New value under the `selector` index or a * function that can be applied to an existing value */ declare function updateItem<T>(selector: number | NoInfer<Predicate<T>>, operatorOrValue: NoInfer<T> | NoInfer<StateOperator<T>>): StateOperator<T[]>; /** * @param selector - index or predicate to remove an item from an array by */ declare function removeItem<T>(selector: number | NoInfer<Predicate<T>>): StateOperator<T[]>; export { append, compose, iif, insertItem, isPredicate, isStateOperator, patch, removeItem, updateItem }; export type { ExistingState, NoInfer, Predicate, StateOperator, ɵPatchSpec };