# Type System Consolidation

All type definitions are now centralized in `src/types/types.ts` as the single source of truth.

## Core Types

### Domain Models (from database)
- **`Word`** - Main vocabulary word with all relations
- **`Example`** - Usage example for a word
- **`Tag`** - Category/tag for organizing words
- **`SeeAlso`** - Related reference (word or grammar page)

### Input Models (for creating records)
- **`NewWord`** - Data needed to create a word
- **`NewExample`** - Data needed to create an example
- **`NewTag`** - Data needed to create a tag
- **`NewSeeAlso`** - Data needed to create a see-also reference

## Type Rules

### Nullable vs Optional
- **Nullable (`| null`)**: Field exists in DB but can be null
  - `type`, `gender`, `note` on `Word`
  - `note` on `Example`, `Tag`, `SeeAlso`

- **Optional (`?`)**: Field may not exist at all
  - `examples`, `tags`, `seeAlso` on `Word` (only included if non-empty)
  - All fields on input types except required ones

### Gender Constraint
- `gender` is constrained to `"m" | "f" | null` (not free-form string)

### Reference Field
- `reference` on `SeeAlso` is **required** (`.notNull()` in schema)
- Should never be empty string

## Migration from Old System

### Removed Types
- Old `VocabWord` in storage.ts (now aliased to `Word`)
- Duplicate `Tag` in storage.ts
- `NewWord` duplicate in storage.ts

### Legacy Aliases (for backward compatibility)
```typescript
export type VocabWord = Word;
export const vocabWordSchema = wordSchema;
```

## Database Schema Types

Drizzle inferred types are exported from `src/lib/db/schema.ts`:
- `DBWord` - Raw database row for words table
- `DBExample` - Raw database row for examples table
- `DBTag` - Raw database row for tags table
- `DBSeeAlso` - Raw database row for see_also table

These should only be used internally by the storage layer. API/components should use the domain types from `types.ts`.
