Skip to main content
On this pageFunctions

FieldValidation

Functions

allValid

functionsource
/**
 * Returns true when every `(state, rules)` pair in the input is
 *  acceptable per `isValid`. Use for form-level submit gates.
 */
(pairs: readonly Array<readonly [
  {
    _tag: "NotValidated"
    value: string
  } | {
    _tag: "Validating"
    value: string
  } | {
    _tag: "Valid"
    value: string
  } | {
    _tag: "Invalid"
    errors: readonly [string, string]
    value: string
  },
  Readonly<{
    isEmpty: (value: string) => boolean
    requiredMessage: Option<RuleMessage>
    rules: readonly Array<Rule>
  }>
]>): boolean

anyInvalid

functionsource
/**
 * Returns true when any state in the input has tag `Invalid`. Use for
 *  "this step/section has errors" affordances, independent of rules.
 */
(states: readonly Array<{
  _tag: "NotValidated"
  value: string
} | {
  _tag: "Validating"
  value: string
} | {
  _tag: "Valid"
  value: string
} | {
  _tag: "Invalid"
  errors: readonly [string, string]
  value: string
}>): boolean

email

functionsource
/** Creates a `Rule` that checks if a string is a valid email format. */
(message: RuleMessage): Rule

endsWith

functionsource
/** Creates a `Rule` that checks if a string ends with a specified suffix. */
(
  suffix: string,
  message?: RuleMessage
): Rule

equals

functionsource
/** Creates a `Rule` that checks if a string exactly matches an expected value. */
(
  expected: string,
  message?: RuleMessage
): Rule

includes

functionsource
/** Creates a `Rule` that checks if a string contains a specified substring. */
(
  substring: string,
  message?: RuleMessage
): Rule

isInvalid

functionsource
/**
 * Returns true when the state's tag is `Invalid`. Tag-only predicate;
 *  unlike `!isValid(rules)(state)`, this does not treat `NotValidated`
 *  or `Validating` as errors. Use for "has the user seen a rule failure
 *  on this field?" affordances like red borders or per-step error
 *  indicators.
 */
(state: {
  _tag: "NotValidated"
  value: string
} | {
  _tag: "Validating"
  value: string
} | {
  _tag: "Valid"
  value: string
} | {
  _tag: "Invalid"
  errors: readonly [string, string]
  value: string
}): boolean

isRequired

functionsource
/**
 * Returns true when the rules mark the field as required. Useful for
 *  rendering affordances like a `*` next to required field labels.
 */
(rules: Rules): boolean

isValid

functionsource
/**
 * Returns true when the field's current state is acceptable given its
 *  rules. For required fields, only `Valid` returns `true`. For optional
 *  fields, `Valid` or `NotValidated` both return `true`. `Invalid` and
 *  `Validating` always return `false`.
 * 
 *  The name is distinct from the `Valid` tag on purpose: `isValid`
 *  answers "is this state an acceptable result?", which for an optional
 *  field is broader than `_tag === 'Valid'`. For pattern-matching on the
 *  state itself, check the `_tag` directly.
 */
(rules: Rules): (state: {
  _tag: "NotValidated"
  value: string
} | {
  _tag: "Validating"
  value: string
} | {
  _tag: "Valid"
  value: string
} | {
  _tag: "Invalid"
  errors: readonly [string, string]
  value: string
}) => boolean

makeRules

functionsource
(options: MakeRulesOptions): Rules

maxLength

functionsource
/** Creates a `Rule` that checks if a string does not exceed a maximum length. */
(
  max: number,
  message?: RuleMessage
): Rule

minLength

functionsource
/** Creates a `Rule` that checks if a string meets a minimum length. */
(
  min: number,
  message?: RuleMessage
): Rule

oneOf

functionsource
/** Creates a `Rule` that checks if a string is one of a specified set of allowed values. */
(
  values: readonly Array<string>,
  message?: RuleMessage
): Rule

pattern

functionsource
/** Creates a `Rule` that checks if a string matches a regular expression. */
(
  regex: RegExp,
  message: RuleMessage
): Rule

resolveMessage

functionsource
(
  message: RuleMessage,
  value: string
): string

startsWith

functionsource
/** Creates a `Rule` that checks if a string begins with a specified prefix. */
(
  prefix: string,
  message?: RuleMessage
): Rule

url

functionsource
/**
 * Creates a `Rule` that checks if a string is a valid URL format.
 * 
 *  By default the URL must include an `http://` or `https://` protocol.
 *  Pass `{ requireProtocol: false }` to accept bare domains.
 */
(options: Readonly<{
  message: RuleMessage
  requireProtocol: boolean
}>): Rule

validate

functionsource
/**
 * Validates a new value and returns the next field state.
 * 
 *  For required fields, an empty value produces `Invalid` with the
 *  required message. For optional fields, an empty value produces
 *  `NotValidated`. Non-empty values run through the field's rules;
 *  the first failure becomes `Invalid`, otherwise the result is `Valid`.
 */
(rules: Rules): (value: string) => {
  _tag: "NotValidated"
  value: string
} | {
  _tag: "Validating"
  value: string
} | {
  _tag: "Valid"
  value: string
} | {
  _tag: "Invalid"
  errors: readonly [string, string]
  value: string
}

validateAll

functionsource
/**
 * Like `validate` but collects every failing rule into the
 *  `Invalid` state's errors array instead of stopping at the first.
 */
(rules: Rules): (value: string) => {
  _tag: "NotValidated"
  value: string
} | {
  _tag: "Validating"
  value: string
} | {
  _tag: "Valid"
  value: string
} | {
  _tag: "Invalid"
  errors: readonly [string, string]
  value: string
}

Types

MakeRulesOptions

typesource
/** Options accepted by `makeRules`. */
type MakeRulesOptions = Readonly<{
  isEmpty: (value: string) => boolean
  required: RuleMessage
  rules: ReadonlyArray<Rule>
}>

Rule

typesource
/** A tuple of a predicate and error message used for field validation. */
type Rule = readonly [Predicate.Predicate<string>, RuleMessage]

RuleMessage

typesource
/** An error message for a rule: either a static string, or a function that receives the invalid value. */
type RuleMessage = string | (value: string) => string

Rules

typesource
/**
 * A field's validation rules: the required message (if any), the list of rules,
 *  and an empty predicate. Produced by `makeRules`; consumed by the module's
 *  operations (`validate`, `validateAll`, `isValid`, `isRequired`, `allValid`).
 *  The fields are accessible but treating them as stable is discouraged.
 *  Prefer the operations so internal shape changes don't break callers.
 */
type Rules = Readonly<{
  isEmpty: (value: string) => boolean
  requiredMessage: Option.Option<RuleMessage>
  rules: ReadonlyArray<Rule>
}>

Constants

Field

constsource
/** The four-state union that represents a field's value in the Model. */
const Field: Union<readonly [
  CallableTaggedStruct<"NotValidated", {
    value: String
  }>,
  CallableTaggedStruct<"Validating", {
    value: String
  }>,
  CallableTaggedStruct<"Valid", {
    value: String
  }>,
  CallableTaggedStruct<"Invalid", {
    errors: NonEmptyArray<String>
    value: String
  }>
]>

Invalid

constsource
/** The `Invalid` state: one or more rules failed. Carries a non-empty `errors` array. */
const Invalid: CallableTaggedStruct<"Invalid", {
  errors: NonEmptyArray<String>
  value: String
}>

NotValidated

constsource
/** The `NotValidated` state: user hasn't interacted yet. */
const NotValidated: CallableTaggedStruct<"NotValidated", {
  value: String
}>

Valid

constsource
/** The `Valid` state: every rule passed. */
const Valid: CallableTaggedStruct<"Valid", {
  value: String
}>

Validating

constsource
/** The `Validating` state: async validation is in flight. */
const Validating: CallableTaggedStruct<"Validating", {
  value: String
}>

Stay in the update loop.

New releases, patterns, and the occasional deep dive.


Built with Foldkit.

© 2026 Devin Jameson