Search code examples
swiftgenericsgeneric-programming

Swift generic without force unwrap downcast


I try to create some generic based code:

protocol ViewModelsCreator {
    associatedtype T: EditItemViewModelType
    func editItemViewModel<T>() -> T
}

class PlacesListViewModel: ViewModelsCreator {
    typealias T = EditPlaceViewModel
    func editItemViewModel<T>() -> T {
        return EditPlaceViewModel()
    }
}

class EditPlaceViewModel: EditItemViewModelType {}

protocol EditItemViewModelType {}

The playground shows error:

cannot convert return expression of type 'EditPlaceViewModel' to return type 'T'

and suggest to use

return EditPlaceViewModel() as! T

Is there any solution to avoid this (as! T) force unwrap code? I think compiler should figure out that EditPlaceViewModel is EditItemViewModelType and should satisfy this generic.


Solution

  • You need to remove the <T> in the ViewModelsCreator protocol and the PlacesListViewModel class.

    protocol ViewModelsCreator {
        associatedtype T: EditItemViewModelType
        func editItemViewModel() -> T
    }
    
    class PlacesListViewModel: ViewModelsCreator {
        typealias T = EditPlaceViewModel
        func editItemViewModel() -> T {
            return EditPlaceViewModel()
        }
    }
    

    You can also remove the typealias and replace -> T with -> EditPlaceViewModel in the PlacesListViewModel class. It works either way but this is more explicit.

    class PlacesListViewModel: ViewModelsCreator {
        func editItemViewModel() -> EditPlaceViewModel {
            return EditPlaceViewModel()
        }
    }