πŸ”„ Type Synchronization

TypeScript ↔ Python type generation.


Overview

The Type Sync Pipeline ensures end-to-end type safety between TypeScript and Python codebases, eliminating type drift.


Pipeline Flow

1
2
3
4
5
6
7
8
9
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Supabase   β”‚ β†’  β”‚  TypeScript  β”‚ β†’  β”‚   Python     β”‚
β”‚   (Schema)   β”‚    β”‚   Types      β”‚    β”‚   Pydantic   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚                   β”‚                   β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          ↓
                    Type Validator
                    (Consistency Check)

Commands

1
2
3
4
5
6
7
8
9
# Full type generation pipeline
just gen-types          # Runs gen-types-ts then gen-types-py

# Individual steps
just gen-types-ts       # Supabase β†’ TypeScript
just gen-types-py       # TypeScript β†’ Python Pydantic

# Validation
just check-types        # Verify consistency, fail if drift detected

Implementation

TypeScript Generation

1
2
3
4
# From Supabase schema
just gen-types-ts

# Output: libs/shared/types/src/database.types.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Generated TypeScript types
export interface Database {
  public: {
    Tables: {
      cases: {
        Row: {
          id: string;
          title: string;
          status: 'open' | 'closed' | 'pending';
          created_at: string;
        };
        Insert: Omit<Row, 'id' | 'created_at'>;
        Update: Partial<Row>;
      };
    };
  };
}

Python Pydantic Generation

1
2
3
4
# From TypeScript types
just gen-types-py

# Output: libs/shared/types-py/src/models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Generated Pydantic models
from pydantic import BaseModel
from typing import Literal
from datetime import datetime

class CaseRow(BaseModel):
    id: str
    title: str
    status: Literal['open', 'closed', 'pending']
    created_at: datetime

class CaseInsert(BaseModel):
    title: str
    status: Literal['open', 'closed', 'pending']

class CaseUpdate(BaseModel):
    title: str | None = None
    status: Literal['open', 'closed', 'pending'] | None = None

Type Mapping

TypeScript Python
string str
number int \| float
boolean bool
Date datetime
null None
T[] list[T]
Record<K, V> dict[K, V]
A \| B A \| B (Union)
'a' \| 'b' Literal['a', 'b']

Validation

Consistency Check

1
just check-types

This verifies that:

  1. TypeScript and Python types are in sync
  2. No manual modifications have drifted
  3. Regeneration produces identical output

Policy

Policy "BidirectionalConsistency" per Constraint Obligation priority 10 as:
  hash(generate_ts(schema)) = hash(reverse_transpile(generate_py(ts)))

CI Integration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# .github/workflows/type-check.yml
jobs:
  type-safety:
    steps:
      - name: Generate Types
        run: just gen-types
      
      - name: Check Consistency
        run: just check-types
      
      - name: Fail on Drift
        run: |
          git diff --exit-code libs/shared/types/
          git diff --exit-code libs/shared/types-py/

Troubleshooting

Issue Solution
Types out of sync Run just gen-types
Supabase schema changed Regenerate from source
Unknown type mapping Add custom mapper in gen_py_types.py