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