def _deserialize_custom_type(
        type_name: str, custom_types: dict[str, Any]
    ) -> Optional[type]:
        """Given a type name like MyType@v1 gets a type from ModelStore or recreates
        it based on the information from the custom types dict that includes fields and
        bases."""
        model_name, version = ModelStore.parse_name_version(type_name)
        fr = ModelStore.get(model_name, version)
        if fr:
            return fr

        if type_name in custom_types:
            ct = CustomType.deserialize(custom_types[type_name], type_name)

            fields = {
                field_name: SignalSchema._resolve_type(field_type_str, custom_types)
                for field_name, field_type_str in ct.fields.items()
            }

            base_model = None
            for base in ct.bases:
                _, _, model_store_name = base
                if model_store_name:
                    model_name, version = ModelStore.parse_name_version(
                        model_store_name
                    )
                    base_model = ModelStore.get(model_name, version)
                    if base_model:
                        break

            return create_feature_model(type_name, fields, base=base_model)

        return None
Given a type name like MyType@v1 gets a type from ModelStore or recreates
        it based on the information from the custom types dict that includes fields and
        bases.
src/datachain/lib/signal_schema.py