ADR-009: Unified Type System
Status
Proposed | Accepted | Superseded by | Deprecates
Version History
- v1: 2025-05-02 - Initial proposal
Context
The current content system implementation has evolved multiple type structures across different layers, leading to inconsistencies, redundant transformations, and unclear boundaries between abstractions. Specific issues include:
Interface Inconsistencies: Different interfaces for similar concepts (
Content
,RawContent
,AdapterContent
) with unclear relationships and conversion patterns.Data Type Handling: Inconsistent handling of content data, with some interfaces using string, others supporting binary data, and unclear transformation patterns between them.
Metadata Structures: Different metadata structures across layers with repeated transformation and normalization.
Environment-Specific Types: Different type structures for browser, Node.js, and other environments without a clear mapping between them.
Transformation Patterns: Ad-hoc transformations between type structures, making it difficult to reason about data flow through the system.
These inconsistencies make the system harder to understand, use, and extend. They also create unnecessary type conversion overhead and potential bugs at the boundaries between abstractions.
Decision
We will implement a unified type system based on generic types and explicit transformations:
Generic Content Interface:
typescriptinterface Content<T = string> { data: T contentType: string metadata: ContentMetadata }
Specialized Content Types:
typescripttype TextContent = Content<string> type BinaryContent = Content<Uint8Array> type JsonContent = Content<Record<string, unknown>> type MdxContent = Content<{ code: string frontmatter: Record<string, unknown> compiledSource?: string }>
Standardized Metadata Interface:
typescriptinterface ContentMetadata { // Core fields uri: string createdAt: Date updatedAt: Date // Optional fields with explicit types title?: string description?: string tags?: string[] // Extension mechanism [key: string]: unknown }
Explicit Transformation Functions:
typescript// Type-safe transformations function transformContent<T, U>( content: Content<T>, transform: (data: T) => U ): Content<U> { return { ...content, data: transform(content.data), } } // Common transformers const stringifyContent = <T>(content: Content<T>): TextContent => transformContent(content, data => JSON.stringify(data)) const parseJsonContent = (content: TextContent): JsonContent => transformContent(content, data => JSON.parse(data))
Environment-Specific Adapters:
typescript// Define storage mechanisms with specific data requirements interface StorageAdapter<T = string> { read(uri: string): Promise<Content<T>> write(uri: string, content: Content<T>): Promise<void> delete(uri: string): Promise<void> list(query?: ContentQuery): Promise<string[]> }
Alternatives Considered
Option 1: Class-Based Type Hierarchy
- Pros: Familiar object-oriented approach, clear inheritance relationships
- Cons: Less flexible than composition, harder to integrate with functional patterns
- Outcome: Rejected as inconsistent with the compositional architecture (ADR-007)
Option 2: Union Types with Type Guards
- Pros: Maintains distinct types without generics, explicit type checking
- Cons: More runtime type checking, harder to compose, more verbose
- Outcome: Partially adopted for validation scenarios, but not as the primary approach
Option 3: Protocol-Based Type System
- Pros: Focuses on behavior rather than structure, potentially more flexible
- Cons: TypeScript has limited support for structural typing, more complex
- Outcome: Rejected due to increased complexity and limited TypeScript support
Option 4: Keep Current Approach with Better Documentation
- Pros: Minimal changes to existing code, low implementation effort
- Cons: Doesn’t address fundamental inconsistencies, technical debt remains
- Outcome: Rejected as it doesn’t solve the underlying problems
Consequences
Benefits
- Type Safety: Generic types provide compile-time safety for different content types
- Consistency: Single Content interface across all layers with clear specialization
- Composability: Transformation functions integrate well with functional composition
- Flexibility: Generic types support both simple and complex content structures
- Clarity: Explicit transformations make data flow through the system more apparent
Challenges
- Migration Effort: Existing code needs to be updated to use the new type system
- Learning Curve: Generic types may be less familiar to some developers
- Performance: Type transformations may introduce slight overhead (though this should be minimal)
- Compatibility: External integrations may need adaptation layers
Implementation
The implementation will proceed in the following phases:
Phase 1: Core Type Definitions
- Create new unified type definitions in
/src/lib/content/types.ts
- Define transformation utilities in
/src/lib/content/transformers.ts
- Update content store interface to use generic types
- Update adapter interfaces to specify data requirements
Phase 2: Adapter Updates
- Update memory adapter to use the generic Content interface
- Update filesystem adapter to standardize on
Content<string>
- Update browser adapters to use appropriate Content specializations
- Create adapter utilities for common transformations
Phase 3: Middleware Updates
- Update validation middleware to use generic Content
- Update caching middleware for consistent type handling
- Update transforming middleware to use explicit transformation functions
- Create middleware utilities for type-safe composition
Phase 4: React Integration Updates
- Update content hooks to leverage generic types
- Create specialized hooks for common content types
- Update components to handle different content types consistently
- Create examples demonstrating type-safe content handling
Documentation Updates
The following documentation will need to be created or updated:
New Documentation:
reference/types/content-types.md
: Comprehensive documentation of the new type systemguides/migration/type-system-migration.md
: Guide for migrating to the new type systemconcepts/content-model/content-structure.md
: Conceptual explanation of content model
Updated Documentation:
- Update adapter documentation with type specialization information
- Update React integration guides with generic type usage
- Update middleware documentation with type transformation patterns
Related Architecture Decisions
- ADR-007: Compositional Content Architecture - The compositional approach influences our type system design
- ADR-003: Registry Facade Architecture - Registry needs to handle unified type system
- ADR-010: Plugin Architecture (Planned) - Will build on this unified type system