- name
- repo-source-code-document
- description
- Write JSDoc comments and inline documentation for Valibot library source code in /library/src/. Use when documenting schemas, actions, methods, or utilities. Covers interface documentation, function overloads, purity annotations, inline comment patterns, and terminology consistency.
# Valibot Source Code Documentation
Documentation patterns for library source code in `/library/src/`.
## JSDoc Patterns
### Interface Documentation
```typescript
/**
* String issue interface.
*/
export interface StringIssue extends BaseIssue<unknown> {
/**
* The issue kind.
*/
readonly kind: 'schema';
/**
* The issue type.
*/
readonly type: 'string';
}
```
**Rules:**
- First line: `[Name] [category] interface.` (e.g., "String issue interface.")
- Property comments: `The [description].` (always start with "The", end with period)
- All properties use `readonly`
- No blank lines between property and its comment
### Function Overloads
Each overload gets its own complete JSDoc:
```typescript
/**
* Creates a string schema.
*
* @returns A string schema.
*/
export function string(): StringSchema<undefined>;
/**
* Creates a string schema.
*
* @param message The error message.
*
* @returns A string schema.
*/
export function string<
const TMessage extends ErrorMessage<StringIssue> | undefined,
>(message: TMessage): StringSchema<TMessage>;
```
**Rules:**
- First line: `Creates a [name] [category].` (use "a" vs "an" correctly)
- Blank line after description
- `@param name The [description].` (start with "The", end with period)
- Blank line after params
- `@returns A [name] [category].` or `@returns The [description].`
### Hints
Add hints after the main description, before `@param`:
```typescript
/**
* Creates an object schema.
*
* Hint: This schema removes unknown entries. To include unknown entries, use
* `looseObject`. To reject unknown entries, use `strictObject`.
*
* @param entries The entries schema.
*
* @returns An object schema.
*/
```
### Links
Link to external resources when relevant using markdown format:
```typescript
/**
* Creates an [email](https://en.wikipedia.org/wiki/Email_address) validation action.
*/
```
### Implementation Function
The implementation has **NO JSDoc** but uses `// @__NO_SIDE_EFFECTS__`:
```typescript
// @__NO_SIDE_EFFECTS__
export function string(
message?: ErrorMessage<StringIssue>
): StringSchema<ErrorMessage<StringIssue> | undefined> {
return {
/* ... */
};
}
```
**`// @__NO_SIDE_EFFECTS__` rules:**
- Add for pure functions (no external state mutation, no I/O)
- Most schema/action/method factories are pure
- **Do NOT add** for functions that mutate arguments (like `_addIssue`)
- Used by bundlers for tree-shaking
### Utility Functions
```typescript
/**
* Stringifies an unknown input to a literal or type string.
*
* @param input The unknown input.
*
* @returns A literal or type string.
*
* @internal
*/
// @__NO_SIDE_EFFECTS__
export function _stringify(input: unknown): string {
// ...
}
```
**Rules:**
- Use `@internal` tag for internal utilities
- Prefix internal functions with `_`
- Only add `// @__NO_SIDE_EFFECTS__` if function is pure
## Inline Comment Patterns
### Section Headers
```typescript
'~run'(dataset, config) {
// Get input value from dataset
const input = dataset.value;
// If root type is valid, check nested types
if (Array.isArray(input)) {
// Set typed to true and value to empty array
dataset.typed = true;
dataset.value = [];
// Parse schema of each array item
for (let key = 0; key < input.length; key++) {
// ...
}
}
}
```
**Rules:**
- Describe WHAT the next code block does
- Present tense verbs: "Get", "Parse", "Check", "Set", "Add", "Create"
- **Omit articles** ("the", "a", "an"): "Get input value" not "Get the input value"
- No period at end
- Blank line before comment, no blank line after
### Conditional Logic
```typescript
// If root type is valid, check nested types
if (input && typeof input === 'object') {
// ...
}
// Otherwise, add issue
else {
_addIssue(this, 'type', dataset, config);
}
```
**Rules:**
- Use "If [condition], [action]"
- Use "Otherwise, [action]" for else branches
- Omit articles
### Hint Comments (Exception)
```typescript
// Hint: The issue is deliberately not constructed with the spread operator
// for performance reasons
const issue: BaseIssue<unknown> = {
/* ... */
};
```
**Rules:**
- Start with "Hint:"
- Explain WHY, not just what
- **CAN use articles** (unlike other inline comments)
- Document performance decisions, non-obvious logic
### TODO Comments
```typescript
// TODO: Should we add "n" suffix to bigints?
if (type === 'bigint') {
/* ... */
}
```
### @ts-expect-error
Used for internal dataset mutations TypeScript can't track:
```typescript
// @ts-expect-error
dataset.typed = true;
```
## File Type Patterns
### Schema Files (`string.ts`, `object.ts`, etc.)
1. Issue interface with JSDoc
2. Schema interface with JSDoc
3. Function overloads with full JSDoc each
4. Implementation with `// @__NO_SIDE_EFFECTS__`
5. Return object with `'~run'` method containing inline comments
### Action Files (`email.ts`, `minLength.ts`, etc.)
1. Issue interface (for validation actions)
2. Action interface with JSDoc
3. Function overloads with JSDoc
4. Implementation with `// @__NO_SIDE_EFFECTS__`
### Method Files (`parse.ts`, `pipe.ts`, etc.)
More complex logic, require more inline comments.
### Utility Files (`_addIssue.ts`, `_stringify.ts`)
1. Single function with JSDoc including `@internal`
2. `// @__NO_SIDE_EFFECTS__` only if pure
## Terminology Consistency
JSDoc descriptions must match the `kind` property if present:
| `kind` Property | JSDoc Wording |
| ------------------ | -------------------------------------- |
| `'schema'` | "Creates a ... schema." |
| `'validation'` | "Creates a ... validation action." |
| `'transformation'` | "Creates a ... transformation action." |
## Quick Reference
### JSDoc First Lines
| Type | Pattern |
| --------- | ------------------------------ |
| Interface | `[Name] [category] interface.` |
| Type | `[Name] [category] type.` |
| Function | `Creates a [name] [category].` |
| Utility | `[Verb]s [description].` |
### Inline Comment Starters
| Pattern | Example |
| ------------------------------ | ---------------------------------------------- |
| `// Get [what]` | `// Get input value from dataset` |
| `// If [condition], [action]` | `// If root type is valid, check nested types` |
| `// Otherwise, [action]` | `// Otherwise, add issue` |
| `// Create [what]` | `// Create object path item` |
| `// Add [what] to [where]` | `// Add issues to dataset` |
| `// Parse [what]` | `// Parse schema of each array item` |
| `// Set [property] to [value]` | `// Set typed to true` |
| `// Hint: [explanation]` | `// Hint: This is for performance` |
| `// TODO: [task]` | `// TODO: Add bigint suffix` |
## Terminology
Use consistently:
- **Schema** (not "validator")
- **Action** (not "validation" for the object)
- **Issue** (not "error" in type names)
- **Dataset** (internal data structure)
- **Config/Configuration** (not "options")
## Checklist
- [ ] Interfaces: `[Name] [category] interface.`
- [ ] Properties: `The [description].`
- [ ] Overloads: Complete JSDoc each
- [ ] Implementation: NO JSDoc
- [ ] Pure functions: `// @__NO_SIDE_EFFECTS__`
- [ ] Impure functions (mutate args): NO `@__NO_SIDE_EFFECTS__`
- [ ] Internal utilities: `@internal` tag
- [ ] Inline comments: No articles (except Hint), no periods
- [ ] JSDoc comments: End with periods
View on GitHub