Swift Can't Infer Generic Type When Generic Type Is Being Passed Through a Parameter

Swift can't infer generic type when generic type is being passed through a parameter

My suggestion is a bit different. It uses static methods

Call loadFromDB and fetch on the NSManagedObject subclass. The benefit is that always the associated type is returned without any further type cast.

Another change is throwing errors. As the Core Data API relies widely on throwing errors my suggestion is to drop CoreDataResult<Value>. All errors are passed through. On success the object is returned, on failure an error is thrown.

I left out the id related code and the update method. You can add a static func predicate(for id : ID)

protocol CoreDataWriteManagerProtocol {
associatedtype ManagedObject : NSManagedObject = Self

static var persistentContainer : NSPersistentContainer { get }
static var entityName : String { get }
static func loadFromDB(predicate: NSPredicate?) throws -> ManagedObject
static func fetch(request: NSFetchRequest<ManagedObject>) throws -> ManagedObject
static func insertNewObject() -> ManagedObject
}

extension CoreDataWriteManagerProtocol where Self : NSManagedObject {

static var persistentContainer : NSPersistentContainer {
return (UIApplication.delegate as! AppDelegate).persistentContainer
}

static var entityName : String {
return String(describing:self)
}

static func loadFromDB(predicate: NSPredicate?) throws -> ManagedObject {
let request = NSFetchRequest<ManagedObject>(entityName: entityName)
request.predicate = predicate
return try fetch(request: request)
}

static func fetch(request: NSFetchRequest<ManagedObject>) throws -> ManagedObject {
guard let results = try? persistentContainer.viewContext.fetch(request) else {
throw CoreDataResponseError.fetch(entityName: entityName)
}
if let result = results.first {
return result
} else {
throw CoreDataResponseError.idDoesNotExist
}
}

static func insertNewObject() -> ManagedObject {
return NSEntityDescription.insertNewObject(forEntityName: entityName, into: persistentContainer.viewContext) as! ManagedObject
}
}

Swift couldn't infer generic type when I was trying to provide my own implementation of AnySequence

The problem with the first implementation is that

let sequence = CustomAnySequence([1, 2, 3])

does not satisfy the constraint in

init<S: Sequence>(_ sequence: S) where S.Iterator == Iterator 

[1, 2, 3] is a sequence, but its iterator type is not your CustomAnyIterator. What you really want is to pass a sequence with the same element type, not the same iterator type:

init<S: Sequence>(_ sequence: S) where S.Element == Element 

and pass sequence.makeIterator() to the init method of CustomAnyIterator.

Note also the inner class can inherit the Element type placeholder from the outer class, and that the type aliases are not really needed.

final class CustomAnySequence<Element>: Sequence {

class CustomAnyIterator: IteratorProtocol {
private let _next: () -> Element?

init<I: IteratorProtocol>(_ iterator: I) where I.Element == Element {
var iterator = iterator
_next = { iterator.next() }
}

func next() -> Element? {
return _next()
}
}

private let _makeIterator: () -> CustomAnyIterator

init<S: Sequence>(_ sequence: S) where S.Element == Element {
_makeIterator = { CustomAnyIterator(sequence.makeIterator()) }
}

func makeIterator() -> CustomAnyIterator {
return _makeIterator()
}
}

You may also consider to use a struct instead of a class.

Swift Generics Generic parameter could not be inferred

It's not possible to implement this correctly. What type is Ztar? How would the compiler know? You've written "fetchData will fetch some kind of data, out of all the infinitely possible kinds of data in the universe, and you, the compiler, should decode it." That's not possible.

Instead, the way this would generally be written is:

fetchData<T: Codable>(ofType: T.Type, completion: @escaping (Result<T, NetworkError>) -> Void)

And then you would need to pass the type you expect as the first parameter:

fetchData(ofType: Record.self) { resultRecord in ... }

If you don't know what type Ztar is, how can the compiler?

(Note that you should almost never use (T?, Error?) as a type. That says "maybe T, maybe Error, maybe neither, maybe both." You almost always mean Result<T, Error> instead. That says "either T or Error.")

Generic parameter 'T' could not be inferred when passing Codable struct

Consider that the parameter in the closure is an instance, not a type. For example like

networkManager.getType(urlString: kGetMyDayTaskDetails + strId, 
header: header) { details in

}

To specify the generic type annotate it and according to the signature it must be optional

networkManager.getType(urlString: kGetMyDayTaskDetails + strId, 
header: header) { (details : MyDayAndTaskDetails?) in

}

Infer Generic Type In Completion Block

You have explicitly declare the type of result in the completion handler when you call the function:

MyClass.requestArray() { (result: Result<[String], Error>) in
switch result {
case .success(let array):
break
case .failure(let error):
break
}
}

Generic parameter 'T' could not be inferred after assignment

This may or may not be a compiler bug.

It is known that Swift does not try to infer the types of some closures, namely, multi-statement ones, as said in SR-1570:

This is correct behavior: Swift does not infer parameter or return types from the bodies of multi-statement closures.

However, your closure consists of only one statement, one declaration to be specific. It is possible, albeit weird, that they designed it so that Swift doesn't try to infer types if the closure contains one declaration as well. For example, this does not compile either

f { let x: Int = $0 } // nothing to do with "g"! The issue seems to be with declarations

If this were by-design, the rationale behind it might be because a single declaration in a closure doesn't make much sense anyway. Whatever is declared, won't be used.

But again, this is just speculation, and this could be a bug as well.

To fix it, simply make it a not-a-declaration:

f { _ = g($0) } // this, without the "let", is IMO the idiomatic way to ignore the function result

Or

f { g($0) } // g has @discardableResult anyway, so you don't even need the wildcard

Type inference with Generics in Swift

If you add a type annotation to the closure parameter then
the compiler can infer the generic type T:

self.getMeGoodies("chocolatechip", callback: { (goodie : Goodie) -> () in
println("eat the \(goodie)")
})

Another method is to pass the type as an argument to the method:

func getMeGoodies<T>(type : T.Type, goodieName : String, callback:(goodie:T) -> ()) {
var goodie:T = 0 //get it from the jug
callback(goodie: goodie)
}

self.getMeGoodies(Goodie.self, goodieName: "chocolatechip", callback: { (goodie) in
println("eat the \(goodie)")
})

Set default or nil value to the generic type parameter of the function

nil is too broad in this case, as the compiler can't infer to which [T]? it should apply the nil.

You will need to explicitly specify the Optional generic argument here:

self.genericCall(param: [StructOne]?.none)

Generic parameter 'T' could not be inferred with closures

You need to explicitly tell the type when calling the function. If you are expecting String then call it with String type.

MyClass.myFunction { (response: String) in

}


Related Topics



Leave a reply



Submit