Skip to content

0.19.1

Choose a tag to compare

@igorbenav igorbenav released this 10 Nov 20:13
· 124 commits to main since this release
335fbe2

FastCRUD 0.19.1

Improved

  • Enhanced Type Safety for Schema-based Column Selection by @igorbenav
    • Added missing @overload signatures for schema_to_select with return_as_model=False
    • Eliminates union types and manual casting when using schema-based column selection with dictionary returns
    • Affects 8 methods: create(), get(), update(), upsert(), upsert_multi(), get_multi(), get_multi_by_cursor(), get_multi_joined()
    • Provides precise type inference for the common pattern of column selection with dict access

Fixed

  • Documentation Link by @igorbenav
    • Fixed broken link in project documentation

Breaking Changes

⚠️ None - This release maintains full backward compatibility with 0.19.0

Details


Enhanced Type Safety for Schema-based Column Selection

Problem Solved

Previously, when using schema_to_select for column selection while keeping return_as_model=False (the default), TypeScript would infer union types that required manual casting:

# Before: Required manual casting
user = await crud.get(db, schema_to_select=UserSchema, username="john")
user = cast(dict[str, Any], user)  # Manual cast needed
if user["tier_id"] is None:  # Now type-safe
    # ...

Solution Implemented

Added missing @overload signatures to handle the common use case where developers want:

  1. Column selection via schema_to_select for performance
  2. Dictionary returns via return_as_model=False (default behavior)
  3. Precise type inference without union types or manual casting
# After: Direct type-safe access
user = await crud.get(db, schema_to_select=UserSchema, username="john")
if user["tier_id"] is None:  # Directly type-safe as Optional[dict[str, Any]]
    # ...

Methods Enhanced

All relevant methods now have complete overload coverage:

  • create() - Create operations with schema selection
  • get() - Single record retrieval with column filtering
  • update() - Update operations with return data selection
  • upsert() - Upsert operations with result formatting
  • upsert_multi() - Bulk upsert with response shaping
  • get_multi() - Multi-record retrieval with field limiting
  • get_multi_by_cursor() - Cursor pagination with column selection
  • get_multi_joined() - Joined queries with selective field returns

New Overload Pattern

Each method now includes the missing overload:

@overload
async def get(
    self,
    db: AsyncSession,
    *,
    schema_to_select: type[SelectSchemaType],
    return_as_model: Literal[False] = False,  # Key addition
    **kwargs: Any,
) -> Optional[dict[str, Any]]: ...

Benefits

  • No More Manual Casting: Eliminates cast(dict[str, Any], result) requirements
  • Better Developer Experience: Precise type inference improves IDE support and catches errors
  • Performance + Convenience: Use schema-based column selection while keeping dict flexibility
  • Backward Compatible: Existing code continues to work unchanged

Real-World Impact

This enhancement addresses a very common pattern where developers:

  • Use schema_to_select to limit returned fields for performance
  • Prefer dictionary access patterns for data manipulation
  • Want to avoid Pydantic model instantiation overhead

What's Changed

Full Changelog: v0.19.0...v0.19.1