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
Purpose of typealias
typealias is literally for creating an "alias" (i.e. another name) for a type. You are not creating a new type, just another name for an existing type. From the Language Reference:
Type aliases do not create new types; they simply allow a name to refer to an existing type.
Therefore, once you declared the typealias,
Graph
and[String: [String]]
now refers to the same type. An extension onGraph
is equivalent to an extension on[String: [String]]
.For your desired behaviour, you need to create a new type. For a
Graph
, I think a struct would be appropriate:struct Graph {
...
}The
Graph
struct can then contain (or, encapsulate) a private property of type[String: [String]]
,private var adjacencyDictionary: [String: [String]]
and you should write methods that accesses, and (optionally) mutates the graph. e.g.
getNode(withName:)
,getNeighboursOfNode(withName:)
,addNode
,addEdge
etc.You should not use a typealias here, because a graph is not a
[String: [String]]
. For example, the following[String: [String]]
is not a (valid) graph:["a": ["b"]]
What is a typealias in Kotlin and how is it being used in this implementation?
It’s often more readable to have dedicated names for function types, such as (Kitty) -> Unit
. In the end, a typealias simply gives us a way to define an alias for such a (e.g.) function type which can then be used throughout the code instead of that explicit type as a 1:1 replacement.
In your example the function type (Kitty) -> Unit
is being aliased with NewKittiesReceived
, which is an argument to the shown function receiveNewKitties
. Every variable holding a function (newKittiesReceived
in the example) can be invoked with function.invoke(arguments...)
or simpler with function(arguments)
.
There’s only a single situation in which the typealias
is used actually: the definition of newKittiesReceived: NewKittiesReceived
will be translated to newKittiesReceived: (Kitty) -> Unit
.
The docs are found here.
When to use typealias?
Actually, there is no doubt that creating a typealias for -let's say- String: typealias MyString = String
wouldn't be that useful, (I would also assume that declaring a typealias for Dictionary with specific key/value type: typealias CustomDict = Dictionary<String, Int>
might not be that useful to you.
However, when it comes to work with compound types you would definitely notice the benefits of type aliasing.
Example:
Consider that you are implementing manager which repeatedly work with closures with many parameters in its functions:
class MyManager {
//...
func foo(success: (_ data: Data, _ message: String, _ status: Int, _ isEnabled: Bool) -> (), failure: (_ error: Error, _ message: String, _ workaround: AnyObject) -> ()) {
if isSuccess {
success(..., ..., ..., ...)
} else {
failure(..., ..., ...)
}
}
func bar(success: (_ data: Data, _ message: String, _ status: Int, _ isEnabled: Bool) -> (), failure: (_ error: Error, _ message: String, _ workaround: AnyObject) -> ()) {
if isSuccess {
success(..., ..., ..., ...)
} else {
failure(..., ..., ...)
}
}
// ...
}
As you can see, the methods signatures looks really tedious! both of the methods take success
and failure
parameters, each one of them are closures with arguments; Also, for implementing similar functions, it is not that logical to keep copy-paste the parameters.
Implementing typealias
for such a case would be so appropriate:
class MyManager {
//...
typealias Success = (_ data: Data, _ message: String, _ status: Int, _ isEnabled: Bool) -> ()
typealias Failure = (_ error: Error, _ message: String, _ workaround: AnyObject) -> ()
func foo(success: Success, failure: Failure) {
if isSuccess {
success(..., ..., ..., ...)
} else {
failure(..., ..., ...)
}
}
func bar(success: Success, failure: Failure) {
if isSuccess {
success(..., ..., ..., ...)
} else {
failure(..., ..., ...)
}
}
// ...
}
Thus it would be more expressive and readable.
Furthermore, you might want to check a medium story I posted about it.
How to create typealias of a function type which refers to a particular function
You cannot assign a function to a typealias
.
You can only assign a type.
typealias mathFunctionType = (Int, Int) -> Int
let mathFunction: mathFunctionType = { int1, int2 in
return int1 + int2
}
Why can I type alias functions and use them without casting?
Turns out, this is a misunderstanding that I had about how Go dealt with types, which can be resolved by reading the relevant part of the spec:
http://golang.org/ref/spec#Type_identity
The relevant distinction that I was unaware of was that of named and unnamed types.
Named types are types with a name, such as int, int64, float, string, bool. In addition, any type you create using 'type' is a named type.
Unnamed types are those such as []string, map[string]string, [4]int. They have no name, simply a description corresponding to how they are to be structured.
If you compare two named types, the names must match in order for them to be interchangeable. If you compare a named and an unnamed type, then as long as the underlying representation matches, you're good to go!
e.g. given the following types:
type MyInt int
type MyMap map[int]int
type MySlice []int
type MyFunc func(int)
the following is invalid:
var i int = 2
var i2 MyInt = 4
i = i2 //both named (int and MyInt) and names don't match, so invalid
the following is fine:
is := make([]int)
m := make(map[int]int)
f := func(i int){}
//OK: comparing named and unnamed type, and underlying representation
//is the same:
func doSlice(input MySlice){...}
doSlice(is)
func doMap(input MyMap){...}
doMap(m)
func doFunc(input MyFunc){...}
doFunc(f)
I'm a bit gutted I didn't know that sooner, so I hope that clarifies the type lark a little for someone else! And means much less casting than I at first thought :)
What is the difference between Type Alias and Type Definition in Go?
type A = string
creates an alias for string
. Whenever you use A
in your code, it works just like string
. So for example, you can't define methods on it.
type A string
defines a new type, which has the same representation as string
. You can convert between an A
and string
at zero cost (because they are the same), but you can define methods on your new type, and reflection will know about the type A
.
For example (on the playground)
package main
import (
"fmt"
)
type A = string
type B string
func main() {
var a A = "hello"
var b B = "hello"
fmt.Printf("a is %T\nb is %T\n", a, b)
}
Output:
a is string
b is main.B
Is it a good idea to use a type alias name in python and then declare that as a variable?
No, decks
is not a type alias. It is a type-annotation. According to PEP-484:
Type aliases are defined by simple variable assignments.
Or according to the typing
documentation:
A type alias is defined by assigning the type to the alias.
So assigning to a variable anything that would be a valid type annotation is a type alias:
decks = Dict[str, Any]
This way decks
would be a type alias.
But when you use the colon, you are annotating that variable, not creating a type alias:
decks: Dict[str, Any]
According to Python's type annotation conventions, you've simply annotated the decks
attribute for DeckManager
instances to have type Dict[str, Any]
.
Use TypeAlias in other class
You need to define the TypeAlias as public
and that too outside the class.
The other option is to define protocol and inherit to any class.
Related Topics
Including Zeros in Front of an Integer
Swift: How to Get Information for an Application Which Is Not Running
How to Make Exponents in the Swiftui
How to Get Exactly the Same Point on Different Screen Sizes
Undefined Symbol Objc_Class_$ When Creating iOS Framework
How to Take a Substring to the First Index of a Character
With Data (Not Nsdata), in Fact How Actually Do You Make a Utf8 Version of a Jpeg
How to Comprehend the "First-Class Function" in Swift
Binary Operator '==' Cannot Be Applied to Operands of Type 'Uilabel' and 'String'
Swift Optional Variable Assignment with Default Value (Double Question Marks)
Equivalent of Skaction Scaletox for a Given Duration in Unity
Update Firebase Multi-Location with Error: Path Is an Ancestor of Path. Swift
Swift Generic Protocol Function Parameters
How to Loop All Firebase Children at Once in the Same Loop
How to Create Lazy Combinations
How to Group an Array of Image Urls Together in Firebase Realtime Database? (Swift)
Label Showing Top of Screen Instead of Being on the Inputaccessoryview