Search Fields
Search Fields are a group of field codecs with fixed URL keys. They describe which URL search params a page or feature area cares about, and how those params are read, written, and inferred.
defineFields is not responsible for running decode or encode. Its job is to establish determinism at definition time:
- Freeze URL keys for fields without
name. - Preserve canonical keys and legacy aliases.
- Let a single field be used directly by hooks.
- Preserve type inference for the whole search values object.
See FieldCodec for FieldCodec properties, and Decode pipeline for decode helper composition.
defineFields
defineFields accepts a group of field codecs and returns a group of named field codecs.
In this definition:
keywordexplicitly uses the URL keyq.pageusespageas the canonical key and supports the old keyp.sortdoes not providename, so it uses the field property key, which issort.
Freezing Names
defineFields freezes each field's URL key into a non-empty name:
- If
nameis not provided, the field property key is used. - If
nameis a string, it is used directly as the URL key. - If
nameis a non-empty array, the first item is the canonical key and the rest are legacy aliases. - If
nameis an empty array, Decurl falls back to the field property key.
The first frozen item is the canonical key. Later items are legacy aliases, mainly for compatibility with old URLs.
If a developer has already provided an explicit name, defineFields is not required. A single named field codec can be passed directly to useSearchValue.
defineFields is better suited for defining page-level Search Fields: it freezes missing name values in bulk and checks duplicate URL keys in development. For page search params maintained by multiple people, it is still recommended to define fields in one place with defineFields.
Named Field
Search Fields let a single field codec carry its URL key, so upper-level APIs do not need another magic string.
This is easier to maintain than this API shape:
String keys are hard to debug once mistyped, while searchFields.keyword carries both the decode rule and the URL key.
Alias Migration
Aliases are used to support old links.
When reading, Decurl tries page first, then p.
When writing, it only uses the first name, the canonical key page.
This gives the following behavior:
TypeScript
A field codec with an explicit name can be passed directly to useSearchValue:
If a field codec does not contain name, a single-field hook cannot know which URL key to read or write, and TypeScript prevents that usage:
A group of Search Fields can continue to infer the full values type through InferFieldValues:
Business code does not need to manually write another search values type. Search Fields are the shared source for URL field mapping and TypeScript values.
Name Conflicts
Multiple fields in the same Search Fields group should not share the same URL key.
This makes decode and encode ambiguous. Decurl warns about duplicate names in development to help catch field definition problems early.
Why Not Dynamic Keys
Decurl does not support passing the URL key and field codec separately:
This looks more flexible, but typos are hard to debug. Similar words such as test and text are not something the type system can analyze; without assistance from intelligent analysis tools such as AI, they are usually hard to notice during review. URL search params are fundamentally string parsing and serialization. For a page or feature area, writing rules as explicit static Search Fields is easier to maintain than assembling them dynamically at call sites.
Freezing name also means the same field codec object is not suitable for reuse across multiple URL keys. This is an intentional trade-off: Decurl values explicit field definitions and clear boundaries more than saving a few lines with the same codec object. Reusing codec objects may cause different pages or fields to share URL semantics that should not be shared, and those problems are usually harder to debug.
If you need reuse, prefer reusing smaller functions, such as decode primitives or custom business decode helpers:
This reuses parsing logic while keeping ownership of each URL key clear.
Boundaries
Search Fields only freeze field mappings. They do not explain a single field's defaultValue, encode, or eq, and they do not actually read or write URLSearchParams.
Those topics are covered by:
- FieldCodec: how a single field decodes, encodes, sets default values, and compares values.
- URLSearchParams: how Search Fields are compiled into a
{ decode, encode }codec.