Skip to content

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.

typescript
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 Zod
  • name: 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.

typescript
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.

typescript
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.

typescript
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.

typescript
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 messages
  • warn(message, meta?) - Log warning level messages
  • info(message, meta?) - Log info level messages
  • debug(message, meta?) - Log debug level messages

LoggerConfig

Configuration interface for Winston logger setup.

typescript
export interface LoggerConfig {
  level: 'error' | 'warn' | 'info' | 'debug';
  outputFile: string | null;
  includeTimestamp: boolean;
  useColors: boolean;
}

Properties:

  • level - Minimum log level to output
  • outputFile - File path for log output (null for console only)
  • includeTimestamp - Whether to include timestamps in logs
  • useColors - Whether to use colored output (console only)

UtilConfig

Configuration interface for utility functions providing optional settings.

typescript
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

typescript
// 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.

typescript
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:

typescript
// 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:

typescript
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: Always true for successful operations
  • data: The actual result data of type T

Error Case: { success: false; error: string }

  • success: Always false for failed operations
  • error: Human-readable error message

Usage Patterns

Basic Usage

typescript
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

typescript
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

typescript
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

typescript
// 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

typescript
// 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

typescript
// 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

typescript
// 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

typescript
// 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

typescript
// ✅ 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

typescript
// ✅ 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

typescript
// ✅ 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

typescript
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

typescript
function createLogger(config: UtilConfig = {}): Logger {
  return {
    log: (message: string) => {
      if (config.debug) {
        console.log(`[DEBUG] ${formatTimestamp(Date.now())}: ${message}`);
      }
    }
  };
}

Type Composition

typescript
// 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>;
}>;

Released under the MIT License.