fieldValidator
fieldValidator<
TCollectionSlug,TValue,TField>(slug,fn):FieldValidate<TCollectionSlug,TValue>
Defined in: packages/core/src/fields/baseTypes.ts:171
Types a field’s validate() against a real collection, DataModel, and
field config, without threading generics through the field factory
(text<Meta, "posts">(...), which also forces you to spell out TFieldMeta).
TCollectionSlug is inferred from slug; supply TValue/TDataModel/TField
explicitly for a typed value/ctx/field.
Each field type builds its own narrower wrapper on top of this — e.g.
textValidator (fields/text/validator.ts) pins TValue to string and
TField to TextField — so authoring a field’s validate never needs
TValue/TField spelled out by hand.
Type Parameters
Section titled “Type Parameters”TCollectionSlug
Section titled “TCollectionSlug”TCollectionSlug extends string
TValue
Section titled “TValue”TValue = unknown
TField
Section titled “TField”TField = unknown
Parameters
Section titled “Parameters”TCollectionSlug
The collection slug doc should be typed as — pass the
same constant the collection itself is defineCollection({ slug })-ed
with (e.g. TABLE_SLUG_PAGES), not a fresh string literal, so a rename
of one renames the other.
FieldValidate<TCollectionSlug, TValue, TField>
The validate function, checked against the real types.
Returns
Section titled “Returns”FieldValidate<TCollectionSlug, TValue>
The same function, re-typed to the field’s loose public validate signature.
Example
Section titled “Example”import { ConvexError } from "convex/values"
slug: text({ validate: textValidator<typeof TABLE_SLUG_PAGES>( TABLE_SLUG_PAGES, async ({ value, doc, ctx, field }) => { const existing = await ctx.db .query("pages") .withIndex("by_slug", (q) => q.eq("slug", value)) .first(); if (existing && existing._id !== doc._id) { throw new ConvexError({ message: `${field.label} must be unique.` }); } }, ),})