Add type safety

This commit is contained in:
Stuart Axelbrooke 2025-07-23 17:56:42 -07:00
parent 4bb8af2c74
commit 58c57332e1

View file

@ -0,0 +1,127 @@
# Dashboard Type Safety Architecture
## Overview
This document describes the type safety architecture implemented in the DataBuild dashboard to prevent runtime errors from backend API changes.
## Problem Statement
The dashboard previously experienced runtime crashes when backend API changes were deployed:
- `status.toLowerCase()` failed when status changed from string to object
- `partition.str` access failed when partition structure changed
- TypeScript compilation passed but runtime errors occurred
## Solution Architecture
### 1. Dashboard Data Contracts
We define stable TypeScript interfaces in `types.ts` that represent the data shapes the UI components expect:
```typescript
export interface DashboardBuild {
build_request_id: string;
status: string; // Always a human-readable string
requested_partitions: string[]; // Always flat string array
// ... other fields
}
```
### 2. Transformation Layer
The `services.ts` file contains transformation functions that convert OpenAPI-generated types to dashboard types:
```typescript
function transformBuildSummary(apiResponse: BuildSummary): DashboardBuild {
return {
build_request_id: apiResponse.build_request_id,
status: apiResponse.status_name, // Extract string from API
requested_partitions: apiResponse.requested_partitions.map(p => p.str), // Flatten objects
// ... transform other fields
};
}
```
### 3. Component Isolation
All UI components use only dashboard types, never raw API types:
```typescript
// GOOD: Using dashboard types
const build: DashboardBuild = await DashboardService.getBuildDetail(id);
m('div', build.status.toLowerCase()); // Safe - status is always string
// BAD: Using API types directly
const build: BuildSummary = await apiClient.getBuild(id);
m('div', build.status.toLowerCase()); // Unsafe - status might be object
```
## Benefits
1. **Compile-time Safety**: TypeScript catches type mismatches during development
2. **Runtime Protection**: Transformation functions handle API changes gracefully
3. **Clear Boundaries**: UI code is isolated from API implementation details
4. **Easier Updates**: API changes require updates only in transformation functions
## Testing Strategy
### Unit Tests
- `transformation-tests.ts`: Verify transformation functions produce correct dashboard types
### Strict TypeScript Configuration
- `exactOptionalPropertyTypes`: Ensures optional properties are handled explicitly
- `strictNullChecks`: Prevents null/undefined errors
- `noImplicitAny`: Requires explicit typing
## Maintenance Guidelines
### When Backend API Changes
1. Update the OpenAPI spec and regenerate client
2. TypeScript compilation will fail in transformation functions if types changed
3. Update only the transformation functions to handle new API shape
4. Run tests to verify UI components still work correctly
### Adding New Features
1. Define dashboard types in `types.ts`
2. Create transformation functions in `services.ts`
3. Use only dashboard types in components
4. Add tests for the transformation logic
## Example: Handling API Evolution
If the backend changes `status` from string to object:
```typescript
// Old API
{ status_name: "COMPLETED" }
// New API
{ status: { code: 4, name: "COMPLETED" } }
// Transformation handles both
function transformBuildSummary(apiResponse: any): DashboardBuild {
return {
status: apiResponse.status_name || apiResponse.status?.name || 'UNKNOWN',
// ... other fields
};
}
```
The UI components continue working without changes because they always receive the expected `string` type.
## Monitoring
To maintain type safety over time:
1. **Build-time Checks**: TypeScript compilation catches type errors
2. **Test Suite**: Transformation tests run on every build
3. **Code Reviews**: Ensure new code follows the pattern
4. **Documentation**: Keep this document updated with patterns
## Related Files
- `types.ts` - Dashboard type definitions
- `services.ts` - API transformation functions
- `transformation-tests.ts` - Unit tests for transformations
- `tsconfig_app.json` - Strict TypeScript configuration