Strict Typing Implementation Guide
This guide provides the roadmap and technical patterns for eliminating all any and unknown types from the TendSocial backend.
Success Metrics
| Metric | Target |
|---|---|
Total any count | 0 |
Total unknown count | 0 |
| ESLint errors | 0 |
| TypeScript errors | 0 |
Technical Patterns
1. Zero-Assertion JSON Parsing
Instead of casting as any or as MyType, use Zod to validate at the boundary.
❌ PROHIBITED:
typescript
const data = JSON.parse(jsonString) as MyType;✅ REQUIRED:
typescript
import { validateJsonField } from '../utils/validation.js';
const data = validateJsonField(jsonString, MyTypeSchema);
if (!data) throw new Error("Invalid data");2. Platform Type Definitions
Every external API must have a corresponding Zod schema.
typescript
// src/types/platforms.ts
export const LinkedInPageMetadataSchema = z.object({
organizationId: z.string(),
organizationName: z.string(),
authorUrn: z.string().optional(),
});
export type LinkedInPageMetadata = z.infer<typeof LinkedInPageMetadataSchema>;3. Strict Job Error Handling
typescript
} catch (error: Error | ErrorResponse) {
// Use helper to safely extract message from unknown type
const message = getErrorMessage(error);
await prisma.job.update({
where: { id: jobId },
data: { status: 'failed', errorMessage: message }
});
});4. Shared Types (Big Bang Refactor)
Major entities share a single canonical definition across the stack.
typescript
// All consumers (Frontend, Backend, AI) use the same package
import { BrandProfile, AppSettings } from '@tendsocial/shared-types';Implementation Roadmap
Phase 1: Core Types & Setup (Completed)
- [x] Basic strict types (
src/types/index.ts) - [x] Strict ESLint config
- [x] Compilation fixes for
genai.tsand core jobs
Phase 2: Platform & AI Types (Completed)
- [x] Create
src/types/platforms.ts(LinkedIn, Twitter, etc.) - [x] Create
src/types/ai.ts(OpenAI, Anthropic adapters) - [x] Refactor platform adapters to use these schemas
Phase 3: Record<string, unknown> Elimination (Completed)
- [x] Replace all
Record<string, unknown>in backend (45+ instances) - [x] Replace all
Record<string, unknown>in frontend (45 instances) - [x] Replace all
Record<string, unknown>in shared-types (4 instances) - [x] Define proper types where structure is known (
VoiceTone,TargetAudience) - [x] Use
unknownonly for truly dynamic/platform-specific data
Phase 4: Full "Unknown" Elimination (Completed)
- [x] Find all remaining
unknowntypes in backend - [x] Replace with specific interfaces/types
- [x] Document cases where
unknownis truly necessary
Phase 5: Full "Any" Elimination (Completed)
- [x] Grep for
: anyand refactor remaining usages - [x] Grep for
as anyand replace with proper type assertions - [x] Fix all implicit
anyfrom untyped imports
Phase 6: Big Bang Shared Types Refactor (Active)
- [x] Create canonical BrandProfile interface & Zod schema
- [x] Create comprehensive
@tendsocial/shared-typespackage - [/] Migrating Database Schema to structured JSON columns
- [ ] Refactoring Backend routes to use shared types (0 mapping)
- [ ] Integrating with Frontend for end-to-end type safety