Configuration
A great out-of-the-box experience is a core goal of ArkType, including safe defaults and helpful messages for complex errors.
However, it's equally important that when you need different behavior, you can easily configure it with the right granularity.
Levels
| Level | Applies To | Example |
|---|---|---|
| default | built-in defaults for all Types | |
| global | all Types parsed after the config is applied | |
| scope | all Types parsed in the configured Scope | |
| type | all Types shallowly referenced by the configured Type |
Some options only apply at specific levels, as reflected in the corresponding input types.
Use the `"arktype/config"` entrypoint in a separate file for global config!
If you need your config to apply to built-in keywords (important for options
like jitless, numberAllowsNaN, dateAllowsInvalid), you should import and
configure from "arktype/config" before importing anything from
"arktype".
Otherwise, keywords will have already been parsed by the time your config applies!
Errors
To allow custom errors to be integrated seemlessly with built-in logic for composite errors (i.e. union and intersection), ArkType supports a set of composable options:
| optional | description | example |
|---|---|---|
| description | ✅ a summary of the constraint that could complete the phrase "must be ___" 🥇 reused by other metadata and should be your first go-to for customizing a message | |
| expected | ✅ a function accepting the error context and returning a string of the format "must be ___" ✅ specific to errors and takes precedence over | |
| actual | ✅ a function accepting the data that caused the error and returning a string of the format "(was ___)" ✅ if an empty string is returned, the actual portion of the message will be omitted | |
| problem | ✅ a function accepting the results of ❌ may not apply to composite errors like unions | |
| message | ✅ a function accepting the result of ❌ may not apply to composite errors like unions |
By Code
Errors can also be configured by their associated code property at a scope or global level.
For example:
ArkErrors
For use cases like i18n that fall outside the scope of this composable message config, the ArkErrors array returned on validation failure contains ArkError instances that can be discriminated via calls like .hasCode("divisor") and contain contextual data specific to that error type as well as getters for each composable error part.
These ArkError instances can be arbitrarily transformed and composed with an internationalization library. This is still a topic we're working on investigating and documenting, so please reach out with any questions or feedback!
Keywords
Built-in keywords like string.email can be globally configured.
This can be very helpful for customizing error messages without needing to create your own aliases or wrappers.
The options you can provide here are identical to those used to configure a Type directly, and can also be extended at a type-level to include custom metadata.
Clone
By default, before a morph is applied, ArkType will deeply clone the original input value with a built-in deepClone function that tries to make reasonable assumptions about preserving prototypes etc. The implementation of deepClone can be found here.
You can provide an alternate clone implementation to the clone config option.
To mutate the input object directly, you can set the clone config option to false.
onUndeclaredKey
Like TypeScript, ArkType defaults to ignoring undeclared keys during validation. However, it also supports two additional behaviors:
"ignore"(default): Allow undeclared keys on input, preserve them on output"delete": Allow undeclared keys on input, delete them before returning output"reject": Reject input with undeclared keys
These behaviors can be associated with individual Types via the built-in "+" syntax (see those docs for more on how they work). You can also change the default globally:
exactOptionalPropertyTypes
By default, ArkType validates optional keys as if TypeScript's exactOptionalPropertyTypes is set to true.
See an example
This approach allows the most granular control over optionality, as | undefined can be added to properties that should accept it.
However, if you have not enabled TypeScript's exactOptionalPropertyTypes setting, you may globally configure ArkType's exactOptionalPropertyTypes to false to match TypeScript's behavior. If you do this, we'd recommend making a plan to enable exactOptionalPropertyTypes in the future.
exactOptionalPropertyTypes does not yet affect default values!
Support for this is tracked as part of this broader configurable defaultability issue.
jitless
By default, when a Type is instantiated, ArkType will precompile optimized validation logic that will run when the type is invoked. This behavior is disabled by default in environments that don't support new Function, e.g. Cloudflare Workers.
If you'd like to opt out of it for another reason, you can set the jitless config option to true.
onFail
In some domains, you may always want to throw on failed validation or transform the result in some other way.
By specifying onFail in your global config, you can control what happens when you invoke a Type on invalid data:
metadata
Additional arbitrary metadata can also be associated with a Type.
It can even be made type-safe via an interface extension ArkType exposes for this purpose:
toJsonSchema
Some ArkType features don't have JSON Schema equivalents. By default, toJsonSchema() will throw in these cases.
This behavior can be configured granularly to match your needs.
a default handler can also be specified at the root of a fallback config:
These options can also be set at a global or scope-level.
Fallback Codes
This is the full list of configurable reasons toJsonSchema() can fail.
| Code | Description |
|---|---|
arrayObject | arrays with object properties |
arrayPostfix | arrays with postfix elements |
defaultValue | non-serializable default value |
domain | non-serializable type keyword (always bigint or symbol) |
morph | transformation |
patternIntersection | multiple regex constraints |
predicate | custom narrow function |
proto | non-serializable instanceof |
symbolKey | symbolic key on an object |
unit | non-serializable === reference (e.g. undefined) |
date | a Date instance (supercedes proto for Dates ) |
prototypes
When you .infer your Types, ArkType traverses them and extracts special values like morphs, e.g. (In: string) => Out<number>.
Though generally this is able to preserve the original type, it is inefficient and can accidentally expand certain object types.
You can use the type-level prototypes config to tell ArkType to treat those types as external: