TypeScript Code Generation
Generate type-safe TypeScript code with full type definitions and modern async/await patterns.
Overview
Circuitry generates TypeScript code that:
- Includes comprehensive type definitions
- Uses modern ES6+ features with types
- Provides interface definitions for data flow
- Supports strict mode compilation
- Works with popular TypeScript frameworks
Generated Code Structure
import { httpRequest, HttpOptions } from 'circuitry-helpers';
import { confirmAction, ConfirmResult } from 'circuitry-ui';
interface WorkflowData {
[key: string]: any;
confirmed?: boolean;
status?: string;
}
async function workflowName(input: WorkflowData = {}): Promise<WorkflowData> {
let data: WorkflowData = input;
try {
// Each node transforms data with type safety
data = await httpRequest('https://api.example.com', {
method: 'GET'
} as HttpOptions);
// Type-safe condition checking
if (data.confirmed === true) {
data = await processBranch(data);
}
return data;
} catch (error) {
console.error('Workflow error:', error);
throw error;
}
}
Type Definitions
Install Type Definitions
# TypeScript helper files include .d.ts definitions
# Download from Code Generation dialog:
# - circuitry-helpers.d.ts
# - circuitry-ui.d.ts
Core Types
// WorkflowData - Main data flow type
interface WorkflowData {
[key: string]: any;
}
// HTTP Options
interface HttpOptions {
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
headers?: Record<string, string>;
body?: any;
timeout?: number;
}
// Confirmation Result
interface ConfirmResult {
confirmed: boolean;
timestamp: string;
context?: any;
}
// Message Result
interface MessageResult {
acknowledged: boolean;
timestamp: string;
message: string;
type: 'info' | 'success' | 'warning' | 'error';
}
// Form Field
interface FormField {
name: string;
label?: string;
type?: 'text' | 'number' | 'email' | 'checkbox' | 'select';
required?: boolean;
defaultValue?: any;
options?: Array<{ value: string; label: string }>;
}
Helper Functions with Types
HTTP Requests
const response: WorkflowData = await httpRequest(
'https://api.example.com/users',
{
method: 'POST',
headers: { 'Authorization': 'Bearer token' },
body: { name: 'John', email: 'john@example.com' }
}
);
User Interactions
// Confirmation with typed result
const confirm: ConfirmResult = await confirmAction('Continue?');
if (confirm.confirmed) {
// Type-safe access
}
// Form input with typed fields
const fields: FormField[] = [
{ name: 'email', type: 'email', required: true },
{ name: 'age', type: 'number' }
];
const formData = await getFormInput(fields);
Configuration
tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Running TypeScript Workflows
Direct Execution with tsx
# Install tsx globally
npm install -g tsx
# Run TypeScript directly
tsx workflow.ts
Compile and Run
# Compile to JavaScript
tsc workflow.ts
# Run compiled JavaScript
node workflow.js
With Node.js and ts-node
# Install dependencies
npm install -D typescript ts-node @types/node
# Run with ts-node
npx ts-node workflow.ts
Framework Integration
Next.js
// app/api/workflow/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { myWorkflow } from '@/lib/workflow';
export async function POST(request: NextRequest) {
try {
const input = await request.json();
const result = await myWorkflow(input);
return NextResponse.json(result);
} catch (error) {
return NextResponse.json(
{ error: error.message },
{ status: 500 }
);
}
}
Express with TypeScript
import express, { Request, Response } from 'express';
import { myWorkflow } from './workflow';
const app = express();
app.use(express.json());
app.post('/workflow', async (req: Request, res: Response) => {
try {
const result = await myWorkflow(req.body);
res.json(result);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000);
Advanced Types
Custom Workflow Types
// Define specific types for your workflow
interface UserData extends WorkflowData {
userId: string;
email: string;
status: 'active' | 'inactive' | 'pending';
metadata?: {
lastLogin: Date;
preferences: Record<string, any>;
};
}
async function userWorkflow(input: Partial<UserData> = {}): Promise<UserData> {
let data: UserData = {
userId: '',
email: '',
status: 'pending',
...input
};
// Type-safe operations
if (data.status === 'active') {
// TypeScript knows status is 'active' here
}
return data;
}
Generic Workflow Functions
// Create reusable typed workflow functions
async function processWorkflow<T extends WorkflowData>(
input: T,
processor: (data: T) => Promise<T>
): Promise<T> {
try {
const processed = await processor(input);
return processed;
} catch (error) {
console.error('Processing failed:', error);
throw error;
}
}
// Usage
const result = await processWorkflow(
{ userId: '123' },
async (data) => {
// Process data
return { ...data, processed: true };
}
);
Type Guards
// Type guard functions for runtime validation
function isConfirmResult(data: any): data is ConfirmResult {
return data &&
typeof data.confirmed === 'boolean' &&
typeof data.timestamp === 'string';
}
// Usage in workflow
const result = await someOperation();
if (isConfirmResult(result)) {
// TypeScript knows result is ConfirmResult here
if (result.confirmed) {
// Continue processing
}
}
Error Handling with Types
// Custom error types
class WorkflowError extends Error {
constructor(
message: string,
public code: string,
public details?: any
) {
super(message);
this.name = 'WorkflowError';
}
}
// Typed error handling
async function safeWorkflow(input: WorkflowData): Promise<WorkflowData> {
try {
return await myWorkflow(input);
} catch (error) {
if (error instanceof WorkflowError) {
console.error(`Workflow error ${error.code}: ${error.message}`);
// Handle specific workflow errors
} else if (error instanceof Error) {
console.error('General error:', error.message);
} else {
console.error('Unknown error:', error);
}
throw error;
}
}
Testing with TypeScript
// workflow.test.ts
import { describe, it, expect } from '@jest/globals';
import { myWorkflow } from './workflow';
describe('Workflow Tests', () => {
it('should process valid input', async () => {
const input: WorkflowData = {
userId: '123',
action: 'process'
};
const result = await myWorkflow(input);
expect(result).toHaveProperty('status');
expect(result.status).toBe('success');
});
it('should handle errors gracefully', async () => {
const input: WorkflowData = {
invalid: true
};
await expect(myWorkflow(input)).rejects.toThrow();
});
});
Best Practices
- Strict Mode: Always enable strict mode in tsconfig.json
- Type Everything: Avoid using 'any' type when possible
- Interfaces: Define interfaces for complex data structures
- Type Guards: Use type guards for runtime validation
- Error Types: Create custom error classes for better error handling