Can You Enforce a Typealias in Swift

Can you enforce a typealias in swift

Swift doesn't (yet?) have the concept of newtype - basically an opaque type backstored with the same values as the original type.

What you could do, is to use 1-field structs that wrap the original type. 1-field structs have no performance penalty while giving you a distinct type to work with, carrying more semantical value ( thanks @RobNapier for the great tip regarding Hashable):

struct EnemyId: Hashable {
private let value: Int

init(_ value: Int) { self.value = value }

static func ==(_ lhs: EnemyId, _ rhs: EnemyId) -> Bool {
return lhs.value == rhs.value
}

var hashValue: Int {
return value.hashValue
}
}

struct WeaponId: Hashable {
private let value: Int

init(_ value: Int) { self.value = value }

static func ==(_ lhs: WeaponId, _ rhs: WeaponId) -> Bool {
return lhs.value == rhs.value
}

var hashValue: Int {
return value.hashValue
}
}

Types like this can be used in many places as an Int would do, while being different. Of course you could add more protocols conformance, based on the needs.

Extending type aliases in swift

typealias just change or rename the type. It does not create another user type for you. You are actually extending Float for Speed, Altitude again.

You can pass 180 to your custom struct by conforming Literals types.

let mySpeed: Speed = 180

FloatLiteralConvertible and IntegerLiteralConvertible will give you same functionality you want and you can directly assign values to your custom struct types as you assign to Float

struct Speed: FloatLiteralConvertible,IntegerLiteralConvertible {

var distance:Float
init(floatLiteral value: Float) {
distance = value
}

init(integerLiteral value: Int){
distance = Float(value)
}

var formatted: String {
return "\(distance * 3.6) km/h"
}
}

let mySpeed: Speed = 180.0
println(mySpeed.formatted) // 5.0 km/h

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

Swift: overriding typealias inside subclass

Unfortunately there is no good workaround for this problem.

The main idea to override the typealias would work in this case but consider the following:

protocol TakeAndGet {
typealias T
func take(value: T)
func get() -> T
}

class FirstClass: TakeAndGet {
typealias T = FirstClass

var property = 0

func take(value: T) {
value.property = 4
}

func get() -> T {
return FirstClass()
}
}

class SecondClass: FirstClass {

typealias T = SecondClass

var property2 = "hello"
}

If the typealias of the SecondClass overrides the other one the take method would work since it takes a subclass which can be treated as the superclass. But the get method cannot implicitly convert FirstClass to SecondClass. Therefore it is not possible to override a typealias.

Now if we want to override the get function with get() -> SecondClass it wouldn't work since it has not the same signature as the one in the superclass. In addition we inherit the get method which results in an ambiguous use:

SecondClass().get() // which type gets returned? SecondClass or FirstClass

So you have to try a different approach.

Swift typealias in protocol and generic types

In your arrayFoo() method, both array and self are arrays
of Fooable elements, but not necessarily with the same underlying
type T, i.e. Element.T and F.T are unrelated types.

You can fix that with an additional constraint
where F.T == Element.T on the type placeholders:

func arrayFoo<F: Fooable, S where F.T == Element.T >(array: Array<F>, transform: (Element, [F]) -> S) -> [S] {
// ...
}

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
}

Use of typealias syntax within protocols in the Swift standard library

Take a look at this answer. Use of a colon shows inheritance, use of an equals sign shows assignment.

In my understanding this means the following:

typealias X // defines associated type X for subclasses to override
typealias X: Y // defines associated type X and requires that it conform to Y
typealias X = Z // defines associated type X with a default of type Z
typealias X: Y = Z // defines associated type X with a default of type Z and requires that any overrides conform to Y

My interpretation seems to be supported by this article on Swift generics:

An associated type is declared by a protocol using the typealias
keyword. It normally set by an item that conforms to that protocol,
although you can supply a default. Like type parameters, an
associated type can be used as a token when building generic type
rules.

The use of the keyword typealias can be misleading for defining associated types and may be replaced by associatedtype in the future.

Define a Swift typealias for any object that implements multiple protocols

The code that you posted has a different meaning from what you'd expect. You're treating AnyObject like a generic type, with UIPickerViewDataSource and UIPickerViewDelegate as type arguments. It's the same thing as creating a Dictionary with Int keys and String values, for example:

var someDictionary: Dictionary<Int, String>

What you're trying to accomplish needs a different construct, called protocol composition. Swift provides it specifically to express types that conforms to multiple protocols. Its syntax is the following, you can use it anywhere you can use regular types:

FirstProtocol & SecondProtocol

Using this feature, your code would become:

// The typealias definition
typealias CellDelegate = UIPickerViewDataSource & UIPickerViewDelegate

// In my UITableViewCell subclass:
weak var delegate: CellDelegate?

Protocol composition is explained in Apple's guide to the Swift language, here.

EDIT: Updated to Swift 3 syntax, thanks @raginmari



Related Topics



Leave a reply



Submit