Patterns & Workflow
Common TypeScript patterns used throughout Connectum and the recommended development workflow.
Named Parameters
Prefer objects with named properties over positional parameters:
typescript
// CORRECT: named parameters
async function createOrder(options: {
userId: string;
items: OrderItem[];
priority?: number;
}): Promise<Order> {
// ...
}
await createOrder({ userId: '123', items: [...] });
// AVOID: positional parameters (hard to read)
async function createOrder(
userId: string,
items: OrderItem[],
priority?: number,
): Promise<Order> {
// ...
}Const Objects Instead of Enums
The standard pattern throughout Connectum:
typescript
// Define the const object
export const ServerState = {
CREATED: 'created',
STARTING: 'starting',
RUNNING: 'running',
STOPPING: 'stopping',
STOPPED: 'stopped',
} as const;
// Derive the union type
export type ServerState = typeof ServerState[keyof typeof ServerState];
// ServerState = 'created' | 'starting' | 'running' | 'stopping' | 'stopped'
// Usage
function handleState(state: ServerState) {
if (state === ServerState.RUNNING) {
// ...
}
}Branded Types
For type-safe identifiers:
typescript
type UserId = string & { readonly __brand: 'UserId' };
type OrderId = string & { readonly __brand: 'OrderId' };
function getUser(id: UserId): User { ... }
function getOrder(id: OrderId): Order { ... }
// Compile-time safety: can't pass OrderId where UserId is expected
const userId = '123' as UserId;
const orderId = '456' as OrderId;
getUser(userId); // OK
getUser(orderId); // Compile error!Strict Null Checks
Always handle nullable values explicitly:
typescript
// The server address is null until started
const port = server.address?.port;
if (port === undefined) {
throw new Error('Server not started');
}
console.log(`Listening on port ${port}`);Type Checking
Run type checking as a separate step (not compilation):
bash
# Check types
pnpm typecheck # or: tsc --noEmit
# Watch mode for development
tsc --noEmit --watchDevelopment Workflow
bash
# Node.js 25+: start with auto-reload (watches for file changes)
node --watch src/index.ts
# Bun: start with auto-reload
bun --watch src/index.ts
# tsx: start with auto-reload (Node.js 18+)
tsx --watch src/index.ts
# Type check in a separate terminal
tsc --noEmit --watch
# Or run once
pnpm typecheck && pnpm startChecklist
Before running your Connectum service, verify:
- [ ] Node.js 25+ installed (
node --version), Bun installed (bun --version), or tsx installed (npx tsx --version) - [ ]
"type": "module"inpackage.json - [ ]
erasableSyntaxOnly: trueintsconfig.json - [ ]
verbatimModuleSyntax: trueintsconfig.json - [ ] No
enumin application code (useconstobjects) - [ ]
import typefor all type-only imports - [ ]
.tsextensions in relative imports - [ ]
node:prefix for built-in modules - [ ] Proto enums handled via two-step generation (if applicable, Node.js only; not needed for Bun or tsx)
Related
- TypeScript Overview -- back to overview
- Erasable Syntax -- constraints and tsconfig.json
- Runtime Support -- Node.js, Bun, tsx
- Proto Enums -- proto enum workaround
