Skip to content

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 ​

MetricTarget
Total any count0
Total unknown count0
ESLint errors0
TypeScript errors0

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.ts and 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 unknown only for truly dynamic/platform-specific data

Phase 4: Full "Unknown" Elimination (Completed) ​

  • [x] Find all remaining unknown types in backend
  • [x] Replace with specific interfaces/types
  • [x] Document cases where unknown is truly necessary

Phase 5: Full "Any" Elimination (Completed) ​

  • [x] Grep for : any and refactor remaining usages
  • [x] Grep for as any and replace with proper type assertions
  • [x] Fix all implicit any from untyped imports

Phase 6: Big Bang Shared Types Refactor (Active) ​

  • [x] Create canonical BrandProfile interface & Zod schema
  • [x] Create comprehensive @tendsocial/shared-types package
  • [/] 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

TendSocial Documentation