Runtime prop validation utilities for development
Tags: utility validation development
The theme library includes runtime validation utilities that provide helpful warnings during development when components receive invalid props.
Overview
These utilities:
- Only run in development mode
- Are tree-shaken in production builds
- Log warnings to console
- Return validation results for conditional logic
Import
<script>
import {
validateRequired,
validateNonEmptyArray,
validateOneOf,
validateRange,
validateProps,
createValidator,
} from '@classic-homes/theme-svelte';
</script>Validation Functions
validateRequired
Check that a required prop is defined:
validateRequired(value, 'propName', 'ComponentName');Example:
<script>
let { id } = $props();
$effect(() => {
validateRequired(id, 'id', 'FormField');
});
</script>Output (if undefined):
[FormField] "id" is requiredvalidateNonEmptyArray
Check that an array prop has items:
validateNonEmptyArray(array, 'propName', 'ComponentName');Example:
<script>
let { options } = $props();
$effect(() => {
validateNonEmptyArray(options, 'options', 'Select');
});
</script>Output (if empty):
[Select] "options" should not be emptyvalidateOneOf
Check that a value is one of allowed options:
validateOneOf(value, allowedValues, 'propName', 'ComponentName');Example:
<script>
let { variant = 'default' } = $props();
$effect(() => {
validateOneOf(
variant,
['default', 'secondary', 'outline', 'ghost', 'destructive'],
'variant',
'Button'
);
});
</script>Output (if invalid):
[Button] "variant" must be one of: default, secondary, outline, ghost, destructive. Got: invalidvalidateRange
Check that a number is within bounds:
validateRange(value, min, max, 'propName', 'ComponentName');Example:
<script>
let { progress = 0 } = $props();
$effect(() => {
validateRange(progress, 0, 100, 'progress', 'ProgressBar');
});
</script>Output (if out of range):
[ProgressBar] "progress" must be between 0 and 100. Got: 150Combining Validations
validateProps
Check multiple validations at once:
const isValid = validateProps([
validateRequired(id, 'id', 'Component'),
validateNonEmptyArray(items, 'items', 'Component'),
validateOneOf(variant, ['a', 'b'], 'variant', 'Component'),
]);Example:
<script>
let { id, options, size } = $props();
$effect(() => {
validateProps([
validateRequired(id, 'id', 'Select'),
validateNonEmptyArray(options, 'options', 'Select'),
validateOneOf(size, ['sm', 'md', 'lg'], 'size', 'Select'),
]);
});
</script>createValidator
Create a bound validator for cleaner code:
const validate = createValidator('ComponentName');
validate.required(value, 'propName');
validate.nonEmptyArray(array, 'propName');
validate.oneOf(value, allowedValues, 'propName');
validate.range(number, min, max, 'propName');Example:
<script>
import { createValidator } from '@classic-homes/theme-svelte';
let { id, options, variant, step } = $props();
const validate = createValidator('CustomSelect');
$effect(() => {
validate.required(id, 'id');
validate.nonEmptyArray(options, 'options');
validate.oneOf(variant, ['default', 'outline'], 'variant');
validate.range(step, 1, 10, 'step');
});
</script>Validation Results
All functions return a result object:
interface ValidationResult {
valid: boolean;
message?: string;
}Use for conditional logic:
<script>
$effect(() => {
const result = validateRequired(value, 'value', 'Input');
if (!result.valid) {
// Handle invalid state
showError(result.message);
}
});
</script>Production Behavior
In production builds, all validation functions:
- Return
{ valid: true }immediately - Don't log any warnings
- Are tree-shaken if unused
This is achieved through the esm-env package's DEV constant.
Best Practices
Validate in $effect: Run validations reactively
$effect(() => { validateRequired(prop, 'prop', 'Component'); });Use createValidator for consistency: Cleaner component code
const validate = createValidator('MyComponent');Validate early: Catch issues at component init
$effect(() => { // Runs immediately and on prop changes validate.nonEmptyArray(items, 'items'); });Group related validations: Use validateProps for multiple checks
validateProps([validate.required(id, 'id'), validate.required(label, 'label')]);
Example: Custom Component
<script lang="ts">
import { createValidator, validateProps } from '@classic-homes/theme-svelte';
interface Props {
id: string;
options: { value: string; label: string }[];
value?: string;
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
}
let { id, options, value = $bindable(''), size = 'md', disabled = false }: Props = $props();
const validate = createValidator('CustomSelect');
$effect(() => {
validateProps([
validate.required(id, 'id'),
validate.nonEmptyArray(options, 'options'),
validate.oneOf(size, ['sm', 'md', 'lg'], 'size'),
]);
});
</script>Related
- Composables - Utility functions
- Stores - State management