Types Reference
Complete TypeScript types and interfaces for Business-as-Code
The Business-as-Code framework provides a comprehensive set of TypeScript types and interfaces for building autonomous business systems. This reference documents all core types, their properties, and usage patterns.
Overview
Business-as-Code uses TypeScript for full type safety across all operations. The type system is designed to be:
- Semantic: Types carry business meaning, not just structure
- Composable: Types can be combined and extended
- Type-Safe: Full TypeScript inference and checking
- Standards-Based: Built on Schema.org, O*NET, and GS1
Type Categories
Execution Types
Types for defining and executing business logic:
- BusinessFunction - Generic executable operations
- BusinessWorkflow - Multi-step processes
- WorkflowStep - Individual workflow steps
- WorkflowTrigger - Workflow activation conditions
- BusinessAgent - Autonomous agents
Data Types
Types for representing business data:
- BusinessResource - Entities and nouns
- BusinessAction - Subject-Verb-Object operations
- BusinessEvent - System events
Query Types
Types for querying and measuring:
- BusinessQuery - Search and filter operations
- BusinessMetric - KPIs and measurements
Type Safety Patterns
Generic Types
Business-as-Code uses TypeScript generics for type-safe operations:
// Function with typed input and output
const calculateDiscount: BusinessFunction<{ price: number; discountPercent: number }, { finalPrice: number; saved: number }> = {
id: 'calculate-discount',
name: 'Calculate Discount',
execute: async (input) => {
const saved = input.price * (input.discountPercent / 100)
return {
finalPrice: input.price - saved,
saved,
}
},
}
// Type inference works automatically
const result = await calculateDiscount.execute({ price: 100, discountPercent: 10 })
console.log(result.finalPrice) // TypeScript knows this is a numberType Guards
Use type guards to narrow types safely:
function isBusinessFunction(value: unknown): value is BusinessFunction {
return typeof value === 'object' && value !== null && 'id' in value && 'execute' in value && typeof value.execute === 'function'
}
function isBusinessWorkflow(value: unknown): value is BusinessWorkflow {
return typeof value === 'object' && value !== null && 'id' in value && 'steps' in value && Array.isArray(value.steps)
}
// Usage
const entity = await loadEntity()
if (isBusinessFunction(entity)) {
const result = await entity.execute(input) // Type-safe
}Type Inference
TypeScript automatically infers types from usage:
// Input and output types are inferred
const addNumbers = {
id: 'add',
name: 'Add Numbers',
execute: async (input: { a: number; b: number }) => {
return { sum: input.a + input.b }
},
} satisfies BusinessFunction
// TypeScript knows the return type
const result = await addNumbers.execute({ a: 1, b: 2 })
console.log(result.sum) // Type: numberDiscriminated Unions
WorkflowStep uses discriminated unions for type safety:
// Different step types have different properties
type WorkflowStep =
| {
type: 'function'
function: string | BusinessFunction
condition?: never
config?: Record<string, any>
}
| {
type: 'condition'
condition: string
function?: never
config?: never
}
| {
type: 'agent'
config: { agentRole: string; permissions?: string[] }
function?: never
condition?: never
}
// TypeScript enforces correct properties per type
const step: WorkflowStep = {
type: 'function',
function: 'send-email', // Valid
// condition: 'x > 5', // Error: not valid for function steps
}Integration with SDK
Types integrate seamlessly with the SDK:
import { $, db, on, send } from 'sdk.do'
import type { BusinessFunction, BusinessWorkflow, BusinessAgent } from 'business-as-code'
// Define typed function
const sendWelcomeEmail: BusinessFunction<{ email: string; name: string }, { messageId: string }> = {
id: 'send-welcome-email',
name: 'Send Welcome Email',
execute: async ({ email, name }) => {
const messageId = await send($.Email.send, {
to: email,
subject: `Welcome ${name}!`,
template: 'welcome',
})
return { messageId }
},
}
// Use in workflow
const onboardingWorkflow: BusinessWorkflow = {
id: 'user-onboarding',
name: 'User Onboarding',
steps: [
{
id: 'send-email',
name: 'Send Welcome Email',
type: 'function',
function: sendWelcomeEmail, // Type-safe
next: 'assign-rep',
},
{
id: 'assign-rep',
name: 'Assign Sales Rep',
type: 'agent',
config: { agentRole: 'sdr' },
},
],
}Type Extensions
Extend core types for custom needs:
// Extend BusinessFunction with retry logic
interface RetryableFunction<TInput = any, TOutput = any> extends BusinessFunction<TInput, TOutput> {
retries?: number
retryDelay?: number
onRetry?: (attempt: number, error: Error) => void
}
// Extend BusinessWorkflow with versioning
interface VersionedWorkflow extends BusinessWorkflow {
version: string
changeLog?: string[]
deprecated?: boolean
replacedBy?: string
}
// Extend BusinessAgent with tools
interface ToolEnabledAgent extends BusinessAgent {
tools: {
id: string
name: string
description: string
execute: (input: any) => Promise<any>
}[]
}Type Utility Functions
Helper functions for working with types:
// Check if value matches type structure
export function isType<T extends { $type: string }>(value: unknown, type: string): value is T {
return typeof value === 'object' && value !== null && '$type' in value && value.$type === type
}
// Extract input type from function
export type InputType<T> = T extends BusinessFunction<infer I, any> ? I : never
// Extract output type from function
export type OutputType<T> = T extends BusinessFunction<any, infer O> ? O : never
// Usage
type CalculateInput = InputType<typeof calculateDiscount>
// Type: { price: number; discountPercent: number }
type CalculateOutput = OutputType<typeof calculateDiscount>
// Type: { finalPrice: number; saved: number }Best Practices
1. Use Explicit Types
Always define explicit types for function inputs and outputs:
// ✅ Good: Explicit types
interface CalculateInput {
price: number
quantity: number
taxRate: number
}
interface CalculateOutput {
subtotal: number
tax: number
total: number
}
const calculate: BusinessFunction<CalculateInput, CalculateOutput> = {
// ...
}
// ❌ Avoid: Implicit any
const calculate: BusinessFunction = {
// Input and output are 'any'
}2. Leverage Type Inference
Let TypeScript infer types when possible:
// ✅ Good: Let TypeScript infer
const workflow = {
id: 'process-order',
name: 'Process Order',
steps: [
/* ... */
],
} satisfies BusinessWorkflow
// ❌ Unnecessary: Manual typing when not needed
const workflow: BusinessWorkflow = {
id: 'process-order',
name: 'Process Order',
steps: [
/* ... */
] as WorkflowStep[],
}3. Use Type Guards
Create type guards for runtime type checking:
// ✅ Good: Type guard for safety
function assertBusinessFunction(value: unknown): asserts value is BusinessFunction {
if (!isBusinessFunction(value)) {
throw new Error('Value is not a BusinessFunction')
}
}
// Usage
const fn = await loadFunction()
assertBusinessFunction(fn)
await fn.execute(input) // Safe to use4. Document Complex Types
Add JSDoc comments for complex types:
/**
* Configuration for a retryable business function
* @property retries - Maximum number of retry attempts (default: 3)
* @property retryDelay - Milliseconds to wait between retries (default: 1000)
* @property backoff - Exponential backoff multiplier (default: 2)
*/
interface RetryConfig {
retries?: number
retryDelay?: number
backoff?: number
}Next Steps
- Types Reference → - Complete type definitions
- Core Concepts → - Understanding the framework
- Getting Started → - Build your first system