diff --git a/packages/n4s/src/runtime/genEnforceLazy.ts b/packages/n4s/src/runtime/genEnforceLazy.ts index a2a814447..c0aedc535 100644 --- a/packages/n4s/src/runtime/genEnforceLazy.ts +++ b/packages/n4s/src/runtime/genEnforceLazy.ts @@ -4,6 +4,7 @@ import { CB, Stringable, Maybe, + DynamicValue, } from 'vest-utils'; import { ctx } from 'enforceContext'; @@ -91,6 +92,7 @@ export type LazyRuleRunners = { export type ComposeResult = LazyRuleRunners & ((value: any) => void); type RegisteredRules = Array<(value: RuleValue) => RuleDetailedResult>; -type LazyMessage = - | string - | ((value: unknown, originalMessage?: Stringable) => string); +type LazyMessage = DynamicValue< + string, + [value: unknown, originalMessage?: Stringable] +>; diff --git a/packages/vast/src/vast.ts b/packages/vast/src/vast.ts index f8df143b1..637d44865 100644 --- a/packages/vast/src/vast.ts +++ b/packages/vast/src/vast.ts @@ -1,4 +1,9 @@ -import { Maybe, isFunction, optionalFunctionValue } from 'vest-utils'; +import { + DynamicValue, + Maybe, + isFunction, + optionalFunctionValue, +} from 'vest-utils'; // eslint-disable-next-line max-lines-per-function export function createState( @@ -87,8 +92,8 @@ export function createState( } } -type StateInput = S | ((prevState?: S) => S); -type SetStateInput = S | ((prevState: S) => S); +type StateInput = DynamicValue; +type SetStateInput = DynamicValue; export type State = CreateStateReturn; export type StateHandlerReturn = [S, (nextState: SetStateInput) => void]; diff --git a/packages/vest-utils/src/defaultTo.ts b/packages/vest-utils/src/defaultTo.ts index 94594358c..08c04def4 100644 --- a/packages/vest-utils/src/defaultTo.ts +++ b/packages/vest-utils/src/defaultTo.ts @@ -1,9 +1,9 @@ import optionalFunctionValue from 'optionalFunctionValue'; -import { Nullish } from 'utilityTypes'; +import { DynamicValue, Nullish } from 'utilityTypes'; export default function defaultTo( - value: Nullish | ((...args: any[]) => Nullish), - defaultValue: T | (() => T) + value: DynamicValue>, + defaultValue: DynamicValue ): T { return optionalFunctionValue(value) ?? optionalFunctionValue(defaultValue); } diff --git a/packages/vest-utils/src/optionalFunctionValue.ts b/packages/vest-utils/src/optionalFunctionValue.ts index 9c93bf1b3..71da983c5 100644 --- a/packages/vest-utils/src/optionalFunctionValue.ts +++ b/packages/vest-utils/src/optionalFunctionValue.ts @@ -1,7 +1,8 @@ import isFunction from 'isFunction'; +import { DynamicValue } from 'utilityTypes'; export default function optionalFunctionValue( - value: T | ((...args: any[]) => T), + value: DynamicValue, ...args: unknown[] ): T { return isFunction(value) ? value(...args) : value; diff --git a/packages/vest-utils/src/tinyState.ts b/packages/vest-utils/src/tinyState.ts index fff607a1e..8a6f7ee9f 100644 --- a/packages/vest-utils/src/tinyState.ts +++ b/packages/vest-utils/src/tinyState.ts @@ -1,13 +1,16 @@ import optionalFunctionValue from 'optionalFunctionValue'; +import { DynamicValue } from 'utilityTypes'; -export function createTinyState(initialValue: S | (() => S)): TinyState { +export function createTinyState( + initialValue: SetValueInput +): TinyState { let value: S; resetValue(); return () => [value, setValue, resetValue]; - function setValue(nextValue: S | ((currentValue: S) => S)) { + function setValue(nextValue: SetValueInput) { value = optionalFunctionValue(nextValue, value); } @@ -18,6 +21,8 @@ export function createTinyState(initialValue: S | (() => S)): TinyState { export type TinyState = () => [ value: S, - setValue: (next: S | ((prev: S) => S)) => void, + setValue: (next: SetValueInput) => void, resetValue: () => void ]; + +type SetValueInput = DynamicValue; diff --git a/packages/vest-utils/src/utilityTypes.ts b/packages/vest-utils/src/utilityTypes.ts index 5926872f5..bb8eb7e5a 100644 --- a/packages/vest-utils/src/utilityTypes.ts +++ b/packages/vest-utils/src/utilityTypes.ts @@ -2,9 +2,9 @@ export type DropFirst = T extends [unknown, ...infer U] ? U : never; -export type Stringable = string | ((...args: any[]) => string); +export type Stringable = string | CB; -export type CB = (...args: any[]) => any; +export type CB = (...args: Args) => T; export type ValueOf = T[keyof T]; @@ -13,3 +13,9 @@ export type Nullish = Nullable | Maybe; export type Nullable = T | null; export type Maybe = T | undefined; + +export type OneOrMoreOf = T | T[]; + +export type DynamicValue = T | CB; + +type TArgs = any[]; diff --git a/packages/vest-utils/src/vest-utils.ts b/packages/vest-utils/src/vest-utils.ts index c875c444a..f6a07ea02 100644 --- a/packages/vest-utils/src/vest-utils.ts +++ b/packages/vest-utils/src/vest-utils.ts @@ -44,4 +44,6 @@ export type { Nullish, Nullable, Maybe, + OneOrMoreOf, + DynamicValue, } from 'utilityTypes'; diff --git a/packages/vest/src/core/context/SuiteContext.ts b/packages/vest/src/core/context/SuiteContext.ts index 048590a0f..b6047bab2 100644 --- a/packages/vest/src/core/context/SuiteContext.ts +++ b/packages/vest/src/core/context/SuiteContext.ts @@ -1,5 +1,6 @@ import { createCascade } from 'context'; import { assign, TinyState, tinyState, cache, CacheApi } from 'vest-utils'; +import { DynamicValue } from 'vest-utils/src/utilityTypes'; import { IsolateTest } from 'IsolateTest'; import { Modes } from 'Modes'; @@ -25,7 +26,7 @@ export const SuiteContext = createCascade((ctxRef, parentContext) => { type CTXType = { exclusion: TExclusion; - inclusion: Record boolean)>; + inclusion: Record>; currentTest?: IsolateTest; groupName?: string; skipped?: boolean; diff --git a/packages/vest/src/exports/parser.ts b/packages/vest/src/exports/parser.ts index 32492f7bd..38498a14c 100644 --- a/packages/vest/src/exports/parser.ts +++ b/packages/vest/src/exports/parser.ts @@ -1,8 +1,8 @@ +import { suiteSelectors } from 'vest'; import { hasOwnProperty, invariant, isNullish, isPositive } from 'vest-utils'; import { ErrorStrings } from 'ErrorStrings'; import { SuiteSummary, TFieldName, TGroupName } from 'SuiteResultTypes'; -import { suiteSelectors } from 'vest'; export function parse( summary: SuiteSummary diff --git a/packages/vest/src/hooks/exclusive.ts b/packages/vest/src/hooks/exclusive.ts index 08560dcfd..ea8c700f6 100644 --- a/packages/vest/src/hooks/exclusive.ts +++ b/packages/vest/src/hooks/exclusive.ts @@ -4,6 +4,7 @@ import { hasOwnProperty, optionalFunctionValue, Maybe, + OneOrMoreOf, } from 'vest-utils'; import { ErrorStrings } from 'ErrorStrings'; @@ -12,9 +13,9 @@ import { TExclusion, useExclusion, useInclusion } from 'SuiteContext'; import { TFieldName, TGroupName } from 'SuiteResultTypes'; import { useIsExcludedIndividually } from 'skipWhen'; -export type ExclusionItem = Maybe; -export type FieldExclusion = Maybe; -export type GroupExclusion = Maybe; +export type ExclusionItem = Maybe>; +export type FieldExclusion = Maybe>; +export type GroupExclusion = Maybe>; /** * Adds a field or a list of fields into the inclusion list diff --git a/packages/vest/src/hooks/include.ts b/packages/vest/src/hooks/include.ts index af3946f37..bab6238be 100644 --- a/packages/vest/src/hooks/include.ts +++ b/packages/vest/src/hooks/include.ts @@ -7,7 +7,8 @@ import { } from 'vest-utils'; import { useExclusion, useInclusion } from 'SuiteContext'; -import { SuiteResult, TFieldName, TGroupName } from 'SuiteResultTypes'; +import { TFieldName, TGroupName } from 'SuiteResultTypes'; +import { TDraftCondition } from 'getTypedMethods'; import { useCreateSuiteResult } from 'suiteResult'; /** @@ -32,13 +33,7 @@ import { useCreateSuiteResult } from 'suiteResult'; export function include( fieldName: F ): { - when: ( - condition: - | F - | TFieldName - | boolean - | ((draft: SuiteResult) => boolean) - ) => void; + when: (condition: F | TFieldName | TDraftCondition) => void; } { const inclusion = useInclusion(); const exclusion = useExclusion(); @@ -52,13 +47,7 @@ export function include( /** * Specifies the inclusion criteria for the field in `include` function. */ - function when( - condition: - | F - | TFieldName - | ((draft: SuiteResult) => boolean) - | boolean - ): void { + function when(condition: F | TFieldName | TDraftCondition): void { const inclusion = useInclusion(); const exclusion = useExclusion(); diff --git a/packages/vest/src/hooks/optional/OptionalTypes.ts b/packages/vest/src/hooks/optional/OptionalTypes.ts index 167881ef5..3108c8082 100644 --- a/packages/vest/src/hooks/optional/OptionalTypes.ts +++ b/packages/vest/src/hooks/optional/OptionalTypes.ts @@ -1,17 +1,18 @@ +import { DynamicValue, OneOrMoreOf } from 'vest-utils'; + import { TFieldName } from 'SuiteResultTypes'; export type OptionalFields = Record; -export type OptionalsInput = F | F[] | OptionalsObject; +export type OptionalsInput = + | OneOrMoreOf + | OptionalsObject; -type OptionalsObject = Record< - F, - (() => boolean) | boolean ->; +type OptionalsObject = Record; type ImmediateOptionalFieldDeclaration = { type: OptionalFieldTypes.CUSTOM_LOGIC; - rule: boolean | (() => boolean); + rule: TOptionalRule; applied: boolean; }; @@ -21,6 +22,8 @@ type DelayedOptionalFieldDeclaration = { rule: null; }; +type TOptionalRule = DynamicValue; + export type OptionalFieldDeclaration = | ImmediateOptionalFieldDeclaration | DelayedOptionalFieldDeclaration; diff --git a/packages/vest/src/isolates/omitWhen.ts b/packages/vest/src/isolates/omitWhen.ts index 962ef848e..781a2cc61 100644 --- a/packages/vest/src/isolates/omitWhen.ts +++ b/packages/vest/src/isolates/omitWhen.ts @@ -3,7 +3,8 @@ import { optionalFunctionValue } from 'vest-utils'; import { Isolate } from 'vestjs-runtime'; import { SuiteContext, useOmitted } from 'SuiteContext'; -import { SuiteResult, TFieldName, TGroupName } from 'SuiteResultTypes'; +import { TFieldName, TGroupName } from 'SuiteResultTypes'; +import { TDraftCondition } from 'getTypedMethods'; import { useCreateSuiteResult } from 'suiteResult'; /** @@ -17,7 +18,7 @@ import { useCreateSuiteResult } from 'suiteResult'; */ // @vx-allow use-use export function omitWhen( - conditional: boolean | ((draft: SuiteResult) => boolean), + conditional: TDraftCondition, callback: CB ): void { Isolate.create(() => { diff --git a/packages/vest/src/isolates/skipWhen.ts b/packages/vest/src/isolates/skipWhen.ts index 30cead134..9c96d9560 100644 --- a/packages/vest/src/isolates/skipWhen.ts +++ b/packages/vest/src/isolates/skipWhen.ts @@ -2,7 +2,8 @@ import { CB, optionalFunctionValue } from 'vest-utils'; import { Isolate } from 'vestjs-runtime'; import { SuiteContext, useSkipped } from 'SuiteContext'; -import { SuiteResult, TFieldName, TGroupName } from 'SuiteResultTypes'; +import { TFieldName, TGroupName } from 'SuiteResultTypes'; +import { TDraftCondition } from 'getTypedMethods'; import { useCreateSuiteResult } from 'suiteResult'; /** @@ -16,7 +17,7 @@ import { useCreateSuiteResult } from 'suiteResult'; */ // @vx-allow use-use export function skipWhen( - condition: boolean | ((draft: SuiteResult) => boolean), + condition: TDraftCondition, callback: CB ): void { Isolate.create(() => { diff --git a/packages/vest/src/suite/getTypedMethods.ts b/packages/vest/src/suite/getTypedMethods.ts index 0217228f9..09453af22 100644 --- a/packages/vest/src/suite/getTypedMethods.ts +++ b/packages/vest/src/suite/getTypedMethods.ts @@ -1,6 +1,6 @@ // import { optional, skipWhen, omitWhen, IsolateTest, group } from 'vest'; import { optional } from 'optional'; -import { CB } from 'vest-utils'; +import { CB, DynamicValue } from 'vest-utils'; import { Isolate, IsolateKey } from 'vestjs-runtime'; import { IsolateTest } from 'IsolateTest'; @@ -33,14 +33,9 @@ export function getTypedMethods< export type TTypedMethods = { include: (fieldName: F) => { - when: ( - condition: boolean | F | ((draft: SuiteResult) => boolean) - ) => void; + when: (condition: F | TDraftCondition) => void; }; - omitWhen: ( - conditional: boolean | ((draft: SuiteResult) => boolean), - callback: CB - ) => void; + omitWhen: (conditional: TDraftCondition, callback: CB) => void; only: { (item: FieldExclusion): void; group(item: GroupExclusion): void; @@ -50,10 +45,7 @@ export type TTypedMethods = { (item: FieldExclusion): void; group(item: GroupExclusion): void; }; - skipWhen: ( - condition: boolean | ((draft: SuiteResult) => boolean), - callback: CB - ) => void; + skipWhen: (condition: TDraftCondition, callback: CB) => void; test: { (fieldName: F, message: string, cb: TestFn): IsolateTest; (fieldName: F, cb: TestFn): IsolateTest; @@ -64,3 +56,8 @@ export type TTypedMethods = { }; group: (groupName: G, callback: () => void) => Isolate; }; + +export type TDraftCondition< + F extends TFieldName, + G extends TGroupName +> = DynamicValue]>; diff --git a/packages/vest/src/suiteResult/selectors/suiteSelectors.ts b/packages/vest/src/suiteResult/selectors/suiteSelectors.ts index 54478fa2d..844340a75 100644 --- a/packages/vest/src/suiteResult/selectors/suiteSelectors.ts +++ b/packages/vest/src/suiteResult/selectors/suiteSelectors.ts @@ -136,7 +136,7 @@ export function suiteSelectors( return getFailures(summary, Severity.WARNINGS, fieldName); } - function getWarning(fieldName?: F): Maybe> { + function getWarning(fieldName?: F): GetSingularResponse { return getFailure(Severity.WARNINGS, summary, fieldName as F); } @@ -146,7 +146,7 @@ export function suiteSelectors( return getFailures(summary, Severity.ERRORS, fieldName); } - function getError(fieldName?: F): Maybe> { + function getError(fieldName?: F): GetSingularResponse { return getFailure(Severity.ERRORS, summary, fieldName as F); } @@ -167,8 +167,8 @@ export function suiteSelectors( } export interface SuiteSelectors { - getWarning(fieldName?: F): Maybe>; - getError(fieldName?: F): Maybe>; + getWarning(fieldName?: F): GetSingularResponse; + getError(fieldName?: F): GetSingularResponse; getErrors(fieldName: F): string[]; getErrors(): FailureMessages; getWarnings(): FailureMessages; @@ -288,3 +288,7 @@ function getFailure( matchingFieldName(summaryFailure, fieldName) )?.message; } + +type GetSingularResponse = Maybe< + string | SummaryFailure +>; diff --git a/packages/vestjs-runtime/src/VestRuntime.ts b/packages/vestjs-runtime/src/VestRuntime.ts index f4ebf7744..7058427ee 100644 --- a/packages/vestjs-runtime/src/VestRuntime.ts +++ b/packages/vestjs-runtime/src/VestRuntime.ts @@ -1,9 +1,10 @@ +import { ErrorStrings } from 'ErrorStrings'; import { createCascade } from 'context'; import { invariant, deferThrow, isNullish, - CB, + // CB, assign, TinyState, text, @@ -12,9 +13,9 @@ import { BusType, bus, Nullable, + DynamicValue, } from 'vest-utils'; -import { ErrorStrings } from 'ErrorStrings'; import { Isolate } from 'Isolate'; import { IsolateInspector } from 'IsolateInspector'; import { IsolateMutator } from 'IsolateMutator'; @@ -71,7 +72,7 @@ export function useXAppData() { } export function createRef( - setter: Record | (() => Record) + setter: DynamicValue> ): StateRefType { return Object.freeze({ historyRoot: tinyState.createTinyState>(null), @@ -80,7 +81,7 @@ export function createRef( }); } -export function persist(cb: T): T { +export function persist any>(cb: T): T { const prev = PersistedContext.useX(); return ((...args: Parameters): ReturnType => {