acoustic-carpenter-78188
02/08/2026, 8:05 AM$ref, but as noted in flyteorg/flyte#6887 (item 1), it does not handle list and map containers with nested models.
When a schema contains list[NestedModel], dict[str, NestedModel], or Optional[NestedModel], the $ref inside items, additionalProperties, or anyOf was not resolved, causing KeyError or incorrect type inference (falling back to str).
## Changes
### Centralized $ref resolution
Instead of inlining $ref resolution at every call site, this PR follows the same approach as flytekit PR #3375: _get_element_type now accepts an optional schema parameter and resolves $ref centrally. This means any container type (list, dict, Optional, or nested combinations) automatically gets $ref support.
### New helper functions
• _resolve_ref: Centralized $ref path resolution to schema definition
• _resolve_property_type: Resolves a JSON schema property to a (name, type) tuple, handling $ref, anyOf, and all type variants
• _resolve_single_type: Resolves the inner type of Optional[T] from the first anyOf element, properly handling $ref, array, object, and primitive types
• _resolve_typed_property: Resolves a property with a known type string (array, object, primitives)
• _is_optional_anyof: Validates that an anyOf truly represents Optional[T] (exactly 2 elements, second is null) instead of blindly assuming any anyOf with $ref is Optional
### Bug fixes
• Optional[T] default values: Fields not in the schema's required list now get default=None in the generated dataclass, so constructing with omitted optional fields works correctly
• Optional[List[Model]] / Optional[Dict[str, Model]]: Previously would crash with KeyError because the code accessed property_val["items"] instead of anyOf[0]["items"] - now handled correctly via _resolve_single_type
• Union[TypeA, TypeB]: Previously any anyOf with $ref was blindly wrapped in Optional - now properly validated
• Optional field inclusion: Properties not in required are included in property_order so fields with defaults (like Optional[X] = None) are not skipped during schema traversal
### __init__ wrapper
Extended dict-to-object conversion to handle list[dict] -> list[Model] and dict[str, dict] -> dict[str, Model].
## Tests
Added test_nested_lists_maps.py with 10 test cases covering:
• list[NestedModel] roundtrip (Pydantic + dataclass)
• dict[str, NestedModel] roundtrip (Pydantic + dataclass)
• Optional[NestedModel] with value and with None
• Optional[NestedModel] omitted (default to None)
• Mixed initialization (dict + object in same list)
• Empty collections ([], {})
All existing type engine tests pass with zero regressions.
Ref: flyteorg/flyte#6887
flyteorg/flyte-sdkacoustic-carpenter-78188
02/13/2026, 12:03 PM