Type Definitions
Complete reference for TypeScript types, interfaces, and type utilities used in the project template.
Core Types
Validation Types
ValidationError
Custom error class for validation failures with structured error information.
export class ValidationError extends Error {
public readonly issues: z.ZodIssue[];
constructor(message: string, issues: z.ZodIssue[]) {
super(message);
this.name = 'ValidationError';
this.issues = issues;
}
public getFormattedMessage(): string {
const issueMessages = this.issues.map(issue =>
`${issue.path.join('.')}: ${issue.message}`
).join('; ');
return `${this.message}: ${issueMessages}`;
}
}
Properties:
issues: z.ZodIssue[]
- Array of validation issues from Zodname: string
- Always 'ValidationError'message: string
- Main error message
Methods:
getFormattedMessage(): string
- Returns formatted error with field details
AppConfig
Type-safe application configuration inferred from Zod schema.
export type AppConfig = z.infer<typeof AppConfigSchema>;
// Equivalent to:
export interface AppConfig {
app: {
name: string;
version: string;
environment: 'development' | 'production' | 'test';
};
server: {
port: number;
host: string;
timeout: number;
};
logging: {
level: 'error' | 'warn' | 'info' | 'debug';
outputFile: string | null;
includeTimestamp: boolean;
useColors: boolean;
};
features: {
enableMetrics: boolean;
enableHealthCheck: boolean;
enableCors: boolean;
};
}
UserInput
Type for validated user input data.
export type UserInput = z.infer<typeof UserInputSchema>;
// Equivalent to:
export interface UserInput {
name: string;
email: string;
age?: number;
preferences?: {
theme: 'light' | 'dark' | 'auto';
notifications: boolean;
language: string;
};
}
ServerConfig
Type for server configuration with validation.
export type ServerConfig = z.infer<typeof ServerConfigSchema>;
// Equivalent to:
export interface ServerConfig {
port: number;
host: string;
timeout: number;
maxConnections: number;
enableSsl: boolean;
sslOptions?: {
keyPath: string;
certPath: string;
};
}
Logging Types
ILogger
Interface for dependency injection and testing of loggers.
export interface ILogger {
error(message: string, meta?: object): void;
warn(message: string, meta?: object): void;
info(message: string, meta?: object): void;
debug(message: string, meta?: object): void;
}
Methods:
error(message, meta?)
- Log error level messageswarn(message, meta?)
- Log warning level messagesinfo(message, meta?)
- Log info level messagesdebug(message, meta?)
- Log debug level messages
LoggerConfig
Configuration interface for Winston logger setup.
export interface LoggerConfig {
level: 'error' | 'warn' | 'info' | 'debug';
outputFile: string | null;
includeTimestamp: boolean;
useColors: boolean;
}
Properties:
level
- Minimum log level to outputoutputFile
- File path for log output (null for console only)includeTimestamp
- Whether to include timestamps in logsuseColors
- Whether to use colored output (console only)
UtilConfig
Configuration interface for utility functions providing optional settings.
export interface UtilConfig {
/** Enable debug logging for operations */
debug?: boolean;
/** Maximum number of retry attempts for operations */
maxRetries?: number;
/** Timeout in milliseconds for operations */
timeout?: number;
}
Properties
debug?: boolean
- Optional: Yes
- Default:
false
- Purpose: Enable verbose logging for debugging operations
- Usage: Pass
{ debug: true }
to enable debug output
maxRetries?: number
- Optional: Yes
- Default:
3
(when implemented) - Purpose: Control retry behavior for operations that might fail
- Usage: Future extensibility for retry logic
timeout?: number
- Optional: Yes
- Default:
30000
(when implemented) - Purpose: Set operation timeout in milliseconds
- Usage: Future extensibility for timeout handling
Usage Examples
// Basic usage with debug
const config: UtilConfig = { debug: true };
formatTimestamp(Date.now(), config);
// Full configuration
const fullConfig: UtilConfig = {
debug: true,
maxRetries: 5,
timeout: 10000
};
// Partial configuration
const partialConfig: UtilConfig = { debug: true };
Result Types
AsyncResult<T>
Generic result type for operations that can succeed or fail, providing type-safe error handling.
export type AsyncResult<T> = {
success: true;
data: T;
} | {
success: false;
error: string;
};
Validation Result Types
All validation functions return Result types for consistent error handling:
// Validation function return types
type ValidationResult<T> =
| { success: true; data: T }
| { success: false; error: string };
// Specific validation results
type AppConfigResult = ValidationResult<AppConfig>;
type UserInputResult = ValidationResult<UserInput>;
type ServerConfigResult = ValidationResult<ServerConfig>;
Usage Pattern:
const result = validateUserInput(userData);
if (result.success) {
// TypeScript knows result.data is UserInput
const user = result.data;
} else {
// TypeScript knows result.error is string
console.error('Validation failed:', result.error);
}
Type Parameters
T
- The type of data returned on successful operations
Union Members
Success Case: { success: true; data: T }
success
: Alwaystrue
for successful operationsdata
: The actual result data of typeT
Error Case: { success: false; error: string }
success
: Alwaysfalse
for failed operationserror
: Human-readable error message
Usage Patterns
Basic Usage
function processData(jsonString: string): void {
const result = safeJsonParse(jsonString);
if (result.success) {
// TypeScript knows result.data exists and is type unknown
console.log('Parsed data:', result.data);
} else {
// TypeScript knows result.error exists and is type string
console.error('Parse error:', result.error);
}
}
Generic Usage
function handleResult<T>(result: AsyncResult<T>): T | null {
if (result.success) {
return result.data; // Type T
} else {
console.error(result.error);
return null;
}
}
// Usage with specific types
const stringResult: AsyncResult<string> = { success: true, data: "hello" };
const numberResult: AsyncResult<number> = { success: false, error: "Invalid number" };
Advanced Pattern Matching
function processResult<T>(
result: AsyncResult<T>,
onSuccess: (data: T) => void,
onError: (error: string) => void
): void {
if (result.success) {
onSuccess(result.data);
} else {
onError(result.error);
}
}
// Usage
processResult(
safeJsonParse('{"key": "value"}'),
(data) => console.log('Success:', data),
(error) => console.error('Error:', error)
);
Type Utilities
Type Guards
// Type guard for AsyncResult success
function isSuccess<T>(result: AsyncResult<T>): result is { success: true; data: T } {
return result.success;
}
// Type guard for AsyncResult error
function isError<T>(result: AsyncResult<T>): result is { success: false; error: string } {
return !result.success;
}
// Usage
const result = safeJsonParse('{"test": true}');
if (isSuccess(result)) {
// TypeScript knows this is the success case
console.log(result.data);
}
Utility Type Examples
// Extract data type from AsyncResult
type DataType<T> = T extends AsyncResult<infer U> ? U : never;
// Example usage
type ParsedDataType = DataType<ReturnType<typeof safeJsonParse>>; // unknown
// Create AsyncResult from existing type
type StringResult = AsyncResult<string>;
type NumberResult = AsyncResult<number>;
type ObjectResult = AsyncResult<{ name: string; age: number }>;
Advanced Type Patterns
Conditional Types
// Conditional type for result handling
type ResultValue<T> = T extends AsyncResult<infer U>
? U
: T;
// Usage
type StringValue = ResultValue<AsyncResult<string>>; // string
type DirectValue = ResultValue<number>; // number
Mapped Types
// Convert all properties to AsyncResult
type AsyncResultify<T> = {
[K in keyof T]: AsyncResult<T[K]>;
};
// Example
interface User {
name: string;
age: number;
}
type AsyncUser = AsyncResultify<User>;
// Result: { name: AsyncResult<string>; age: AsyncResult<number>; }
Template Literal Types
// Type-safe error messages
type ErrorPrefix = 'PARSE_ERROR' | 'NETWORK_ERROR' | 'VALIDATION_ERROR';
type ErrorMessage<T extends ErrorPrefix> = `${T}: ${string}`;
// Usage
type ParseError = ErrorMessage<'PARSE_ERROR'>; // "PARSE_ERROR: ${string}"
Type Safety Best Practices
Explicit Type Annotations
// ✅ Good - explicit return type
export function safeJsonParse(jsonString: string): AsyncResult<unknown> {
// Implementation
}
// ❌ Bad - implicit return type
export function safeJsonParse(jsonString: string) {
// TypeScript infers the type, but it's not explicit
}
Generic Constraints
// ✅ Good - constrained generic
function processConfig<T extends UtilConfig>(config: T): T {
return { ...config, debug: true };
}
// ❌ Bad - unconstrained generic
function processConfig<T>(config: T): T {
// Can't safely access config properties
}
Discriminated Unions
// ✅ Good - discriminated union (AsyncResult is an example)
type Result =
| { success: true; data: unknown }
| { success: false; error: string };
// ❌ Bad - non-discriminated union
type Result = {
success: boolean;
data?: unknown;
error?: string;
};
Integration Examples
With Async Functions
async function fetchUserData(id: string): Promise<AsyncResult<User>> {
try {
const response = await fetch(`/api/users/${id}`);
const data = await response.json();
return { success: true, data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
With Configuration
function createLogger(config: UtilConfig = {}): Logger {
return {
log: (message: string) => {
if (config.debug) {
console.log(`[DEBUG] ${formatTimestamp(Date.now())}: ${message}`);
}
}
};
}
Type Composition
// Combine types for complex scenarios
interface ApiConfig extends UtilConfig {
baseUrl: string;
apiKey?: string;
}
type ApiResult<T> = AsyncResult<{
data: T;
status: number;
headers: Record<string, string>;
}>;