String extension documentation
This page documents the explicit String extension path. For ordinary application code, prefer schema-dsl/pure + s. Use this page when you intentionally want direct string-chain authoring, or when you need to maintain compatibility with code that already uses it.
Core features
After explicitly enabling String extensions, strings can directly call chain methods
Advantages:
- ✅ More concise and natural
- ✅ Reduce the amount of code
- ✅ Can coexist with
s('...')seeds ands.xxx()factories
Default alternative: no prototype mutation
If you do not want to modify String.prototype, import from schema-dsl/pure and use s('...') or s.xxx() factories from the start:
Side-effect-controlled entries
The root schema-dsl entry is side-effect-free in v3. Use the explicit entries below only when you intentionally want direct string-chain authoring.
For builds that want String-chain authoring without runtime prototype mutation, use transformSchemaDsl() or schemaDslEsbuildPlugin() to rewrite static chains into s('...') calls that import from schema-dsl/pure. The default transform covers the full built-in String extension method set and naked pipe enums; add user-defined methods with additionalMethods, and add registered custom DSL type literals with additionalTypes or additionalTypePatterns.
Available direct String methods
The following methods are installed on String.prototype by schema-dsl/compat, schema-dsl/register-string, or an explicit installStringExtensions() call. This list mirrors the runtime STRING_EXTENSION_METHODS list. DslBuilder.length(n) and DslBuilder.trim() are intentionally not installed because JavaScript strings already have native .length and .trim() members.
Examples:
quick start
Detailed example
The following examples assume direct String extensions have been explicitly registered. If you do not want runtime prototype mutation, use s('...') or s.xxx() instead.
1. Regularity validation
Correct error code:
'required'- required field'min'- minimum length/value'max'- maximum length/value'pattern'- Regular validation'format'- Format validation (email/url, etc.)'enum'- enumeration value
2. Customize error messages
Message template variables:
{{#label}}- field label{{#limit}}- constraint value (min/max){{#value}}- current value{{#pattern}}- regular expression
3. Custom validator
⚠️ .custom() supports synchronous functions; when asynchronous library checking or remote calling is required, you can return Promise and use validateAsync(). Synchronous validate() will return an explicit error when encountering a Promise-returning custom validator.
Supported return values:
- Do not return/
undefined→ Validation passed ✅ - return string → validation failed (error message)
- Return
{ error, message }→ Custom error code - throw exception → validation failed
- Return
true→ Validation passed - Return
false→ Authentication failed (default message)
Notice:
- The current version supports returning
Promisein.custom(), but must be performed throughvalidateAsync(). - If you want to leave the database/RPC/HTTP check in the business layer, you can also use
schema-dslto do structure validation first, and then perform asynchronous checking in the business layer.
5. Default validator
username default:
'short'- 2-16'medium'- 3-32 (default)'long'- 5-64'3-32'- Custom scope
phone supported countries:
'cn'- China (11th place)'us'- United States'uk'- United Kingdom
password strength:
'weak'- 6-64'medium'- 8-64 (default)'strong'- 8-64 (uppercase and lowercase + numbers)
6. Complete form example
Multi-language support
Solution 1: Global multi-language configuration (recommended)
Option 2: Field-level multilingualism
Option 3: Dynamic switching at runtime
Recommended solution: Solution 1 (global configuration) + Solution 2 (special field coverage)
Compatibility installation and cleanup
Compatibility installation
schema-dsl/compat and schema-dsl/register-string install String extensions on import. Root and pure imports remain side-effect-free.
The extension is mounted to String.prototype with non-enumerable attributes, and detects external methods with the same name during installation; if it is found that the method is not installed by schema-dsl itself, it will refuse to overwrite it.
If your running environment has extended a method with the same name (such as String.prototype.label) before importing an explicit String-install entry, that entry throws a conflict error instead of silently overwriting the external implementation. The side-effect-free root entry does not trigger this conflict check.
Disable after an explicit install
Re-enable or customize the installation
best practices
1. Use pure DSL for simple fields
2. Use chain calls for complex fields
3. Follow the 80/20 rule
Use pure DSL strings for simple fields. Use direct string chains only when that authoring style is intentional; otherwise use s('...') for explicit DSL seeds with builder hints or s.xxx() factories for the strongest method discovery. In TypeScript, direct string chain hints require schema-dsl/string-types.
FAQ
Q1: Will String expansion pollute the global situation?
A: Direct String chains modify String.prototype, so they are opt-in. Root and pure imports do not mutate the prototype. When you intentionally want direct string chains, import schema-dsl/register-string during application startup. uninstallStringExtensions() is mainly for test cleanup or legacy compatibility checks.
Q2: How is the performance?
A: Treat String extension overhead as an ergonomics concern rather than a permanent performance claim. For hot paths, reuse schema objects and validators, then verify with the benchmark route described in Performance Optimization Guide.
Q3: Is TypeScript supported?
A: Fully supported. Use s('...') or s.xxx() for the default no-global-type path, or import schema-dsl/string-types when a TypeScript project intentionally wants String-chain IDE hints for code that is compiled through the transform.
Q4: What is the correct error code?
A:
'required'- required'min'/'max'- length/value range'pattern'- Regular'format'- format (email/url)'enum'- enumeration
Q5: How to support multiple languages?
A: Use Locale global configuration (recommended) or field-level .messages() override.
Related documents
Corresponding sample file
Example entry: string-extensions.ts
Description: Covers the installation/uninstallation of String.prototype extension, chained .label() / .messages() / .pattern() calls, and validation success/failure paths.