Search code examples
swiftxcode13swift5swift-concurrency

Swift 5.5 Concurrency: creating a task with custom error type


I need to use my own custom error enum in tasks that I create:

enum MyError: Error {
 case someError
}

var myTask: Task<MyModel, MyError> = Task { () throws -> MyModel in
            // in case of an error: 
            // throw .someError
            // ... perform some work
            return MyModel()
        }

but I got the following error at the beginning of Task initializer: Referencing initializer 'init(priority:operation:)' on 'Task' requires the types 'MyError' and 'Error' be equivalent.

How can I restrict the Task to only throw errors that are of my custom error type MyError ?


Solution

  • Omit the unnecessary type declaration:

    var myTask = Task { () throws -> MyModel in
        // in case of an error:
        throw MyError.someError
        // ... perform some work
        return MyModel()
    }
    

    The compiler implicitly (and rightly) types myTask as a Task<MyModel, Error>. The compiler doesn't care that what you throw is a MyError, because that's a form of Error.


    Okay, I see now that the issue is merely that you asked the wrong question. You want to know why you can't declare this Task as a Task<MyModel,MyError>.

    The reason is because of how this initializer is declared:

    extension Task where Failure == Error {
        public init(priority: TaskPriority? = nil, operation: @escaping @Sendable () async throws -> Success)
    }
    

    Do you see? This initializer is available only where Failure == Error. That's ==, not :. Using this initializer doesn't require that the Failure type be an Error, it requires that it be Error.