Yay!
That means a short re-visit to the Go spec, as we look at things that have changed.
From the release notes we see that there’s really only one significant change:
Changes to the language¶
Go 1.24 now fully supports generic type aliases: a type alias may be parameterized like a defined type. See the language spec for details. For now, the feature can be disabled by setting
GOEXPERIMENT=noaliastypeparams
; but thealiastypeparams
setting will be removed for Go 1.25.
So let’s take a look at the language spec for those details…
Alias declarations
An alias declaration binds an identifier to the given type [Go 1.9].
AliasDecl = identifier [ TypeParameters ] "=" Type .
The big change here is the addition of [ TypeParameters ]
. In earlier versions of Go, aliases of generic types were not allowed.
Then we also have the following new explanation:
If the alias declaration specifies type parameters [Go 1.24], the type name denotes a generic alias. Generic aliases must be instantiated when they are used.
type set[P comparable] = map[P]bool
In an alias declaration the given type cannot be a type parameter.
type A[P any] = P // illegal: P is a type parameter
I think that’s pretty well explained already. And pretty intuitive (well, as intuitive as aliases and generics ever are).
So I’ll use the rest of today’s email to reiterate the differences between a type alias, and a distinct named type. Because there seems to be no end to confusion on this matter.
Let’s take the example from above, and slightly modify it:
type set1[P comparable] = map[P]bool
type set2[P comparable] map[P]bool
What’s the difference between set1
and set2
here? They seem to have the same underlying type, right?
The former (set1
) is an alias. This means you can logically replace set[P]
anywhere you see it in code with map[P]bool
and vice versa. The two expressions are interchangeable. Neither holds more or less type information than the other.
The latter (set2
) is a distinct type. This means that set2[P]
and map[P]bool
are distinct types (although you can convert between them if you wish). It also means that you can create methods on set2
—something you cannot do for aliases.