Generic typealias in Swift
Generic typealias
can be used since Swift 3.0. This should work for you:
typealias Parser<A> = (String) -> [(A, String)]
Here is the full documentation: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/typealias-declaration
Usage (from @Calin Drule comment):
func parse<A>(stringToParse: String, parser: Parser)
What is the purpose of declaring typealias for generic type parameter
Declaring a public typealias makes it possible to access the generic type parameter outside of the closed generic type.
For example if you declare a typealias WidgetFoo = Foo<Widget>
and keep using WidgetFoo
in other places it will be possible to access its T
via WidgetFoo.Element
(which refers to Widget
) whereas you cannot access the generic type parameter E
itself. This enables robust and refactoring friendly code - imagine you want to replace Widget
with BetterWidget
you only have to change one place (the type alias declaration) and no other because WidgetFoo.Element
will then refer to BetterWidget
.
Example code (provided by @Airspeed Velocity)
struct S<T> { typealias U = T }
typealias TA = S<Int>
let x: TA.T // 'T' is not a member type of 'TA' (aka 'S<Int>')
let y: TA.U
typealias generic function
Swift 4.1 supports generic type aliases. You can use this feature to provide a name for function with generic parameters.
You may have to use such declaration:
typealias Callback<T> = (Result<T>) -> ()
Extending generic typealias
Please notice that typealiases are just labels for existing types, so this:
extension StringArray {
//Some methods
}
Is the same as this:
extension Array<String> {
//Some methods
}
And that doesn't compile because it is not how extensions work. You must insert the where
clause if you want to filter generics. For more information about extensions:
https://docs.swift.org/swift-book/LanguageGuide/Extensions.html
For more information about generic where
clauses in extensions: https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID553
How do I define generic typealias for Swift to return specific types of objects?
As mentioned in the comments, T
is not defined at class-scope. You need to specify the generic type with the class declaration so it can be used across your class.
Try this:
class PersistentStoreCoordinatorMock<T: NSManagedObject>: Storageable {
var objects = [T]() // here I need to define return array
func findAll(of type: T.Type, predicate: NSPredicate) -> [T] {
findAllWasCalled = true
return objects //here I need to return this when that function was called
}
}
Cast a Swift generic class to a protocol with a typealias
Your return type is impossible in today's Swift. A protocol with an associated type (PAT) is abstract. Applying a where clause doesn't change that. Consider this code:
let x: <WHAT-GOES-HERE?> = test()
What type would x
be here? There is nothing you could write there that would compile. What would x.Type
return? What you want it to be is Protocol where Protocol.Thing == Int
, but that's not a type in Swift. It's a type constraint. That's the only way PATs can be used today. That's why you can't have a property of type CollectionType<Int>
, and why you can't write your test()
function.
The solution is a type-eraser to convert your protocol into a concrete struct. For example:
protocol Protocol {
typealias Thing
func dosomething() -> Thing?
}
class Class<X>: Protocol {
typealias Thing = X
func dosomething() -> Thing? {
return nil
}
}
struct AnyProtocol<Thing> {
var _dosomething: () -> Thing?
func dosomething() -> Thing? {
return _dosomething()
}
}
func test() -> AnyProtocol<Int> {
return AnyProtocol(_dosomething: Class<Int>().dosomething)
}
It is possible that some future version of Swift would automatically generate these type erasers for you, but I'm not aware of any specific Swift-evolution proposal for one, so we have to write them by hand today.
For more on building and using type erasers, see A Little Respect for AnySequence.
Swift Initialize struct based on typealias
The problem you're seeing stems from the fact that you not haven't constrained the associate type WriterType
within JsonProperties
.
Currently, it accepts any WriterType
type conforming to Writer
, regardless of what its Model
is.
What you probably want is for the WriterType
type to have its Model
be the same as the type being conformed to JsonProperties
protocol - so you need to constrain it:
protocol JsonProperties: Codable {
associatedtype WriterType: Writer where WriterType.Model == Self
}
Related Topics
Context Menu Not Updating in Swiftui
Unsafemutablepointer<Void> to Concrete Object Type
Callback Url Not Approved Despite Being Provided Twitter API
How to Grant Discoveruserinfowithuserrecordid Permission
Problems Accessing Calendar Using Ekeventstore on Osx Sierra with Swift 3
Compactmap on Sequence() Not Lazy
Subclass Uiscrollview in Swift for Touches Began & Touches Moved
Anyobject Try Cast to Equatable
What Is Existentialmetatype in Swift
How to Add an Admob Gadbannerview to Every View
Testing Protocol Conformance with Associated Types
Safari App Extension Crashes After a Few Seconds for Hello World Project
Workarounds for Generic Variable in Swift
Shared Cookies with Wkprocesspool for Wkwebview in Swift
In What Situation Would One Use Expectationfornotification in Swift Testing
Swift; Delegate Embedded View Controller and Parent
Swift How to Assign a String to a Uitextfield
Alamofire with Custom Parameter Encoding for Swift Application