Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/gaeljw/typetrees
This library is intended to solve the use case of getting the erased types of a (generic) parameter. Something which was possible in Scala 2 with TypeTag and is now a bit more complex with Scala 3.
https://github.com/gaeljw/typetrees
classtag generics scala scala3 typetag
Last synced: 10 days ago
JSON representation
This library is intended to solve the use case of getting the erased types of a (generic) parameter. Something which was possible in Scala 2 with TypeTag and is now a bit more complex with Scala 3.
- Host: GitHub
- URL: https://github.com/gaeljw/typetrees
- Owner: gaeljw
- License: apache-2.0
- Created: 2021-02-10T13:44:33.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-10-18T16:27:32.000Z (19 days ago)
- Last Synced: 2024-10-18T16:47:19.806Z (19 days ago)
- Topics: classtag, generics, scala, scala3, typetag
- Language: Scala
- Homepage:
- Size: 91.8 KB
- Stars: 10
- Watchers: 2
- Forks: 1
- Open Issues: 9
-
Metadata Files:
- Readme: README.adoc
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
:testdir: src/test/scala/io/github/gaeljw/typetrees
= TypeTrees
:toc:[link=https://search.maven.org/artifact/io.github.gaeljw/typetrees_3]
image::https://img.shields.io/maven-central/v/io.github.gaeljw/typetrees_3.svg[]
image::https://github.com/gaeljw/typetrees/workflows/Scala%20CI/badge.svg[]This library is intended to solve the use case of getting the erased types of a (generic) parameter.
Something which was possible in Scala 2 with `+TypeTag+`
and is now a bit more complex with Scala 3.== Get it
.sbt
[source]
----
libraryDependencies += "io.github.gaeljw" %% "typetrees" % typetreesVersion
----.Maven
[source,xml]
----io.github.gaeljw
typetrees_${scala.version}
${typetrees.version}----
== Usage
Two implementations are available:
* using implicits (`given` s)
* using macro|===
|Implementation |Pros 👍 |Cons 👎|Implicits
|Easier
|Only supports up to 4 generic parameters (i.e. a type `T[A, B, C, D]`)|Macro
|Can handle all cases
|Requires to be used in `inline` method
|====== Using implicits
[source,scala]
----
import io.github.gaeljw.typetrees.TypeTree
import io.github.gaeljw.typetrees.TypeTreeTagimport scala.reflect.ClassTag
val tag: TypeTreeTag = summon[TypeTree[T]].tag // <1>
val classTag: ClassTag[_] = tag.self // <2>
val actualClass: Class[_] = classTag.runtimeClassval typeParameters: List[TypeTreeTag] = tag.args // <3>
----
<1> Get a `+TypeTreeTag+` for a generic type `+T+`
<2> Get a `+ClassTag+` for this type
<3> Get a `+TypeTreeTag+` for each type parameters if any==== Examples
The main usage is as follows:
[source,scala]
----
def someGenericMethod[T](t: T)(using typeTree: TypeTree[T]): String = {
val tag: TypeTreeTag = typeTree.tag
s"I have been called with a parameter of type $tag"
}someGenericMethod(Map[String, Int]())
// Gives: I have been called with a parameter of type TypeTreeTag(scala.collection.immutable.Map,List(TypeTreeTag(java.lang.String,List()), TypeTreeTag(Int,List())))
----Or with context bounds:
[source,scala]
----
def someGenericMethod[T : TypeTree](t: T): String = {
val tag: TypeTreeTag = summon[TypeTree[T]].tag
s"I have been called with a parameter of type $tag"
}
----You can find more examples in our link:{testdir}/TestBehaviorImplicits.scala[tests].
=== Using macro
[source,scala]
----
import io.github.gaeljw.typetrees.TypeTreeTag
import io.github.gaeljw.typetrees.TypeTreeTagMacros.typeTreeTagimport scala.reflect.ClassTag
val tag: TypeTreeTag = typeTreeTag[T] // <1>
val classTag: ClassTag[_] = tag.self // <2>
val actualClass: Class[_] = classTag.runtimeClassval typeParameters: List[TypeTreeTag] = tag.args // <3>
----
<1> Get a `+TypeTreeTag+` for a generic type `+T+`
<2> Get a `+ClassTag+` for this type
<3> Get a `+TypeTreeTag+` for each type parameters if any==== Examples
The main usage is as follows, within a generic `+inline+` method:
[source,scala]
----
inline def someGenericMethod[T](t: T): String = {
val tag: TypeTreeTag = typeTreeTag[T]
s"I have been called with a parameter of type $tag"
}someGenericMethod(Map[String, Int]())
// Gives: I have been called with a parameter of type TypeTreeTag(scala.collection.immutable.Map,List(TypeTreeTag(java.lang.String,List()), TypeTreeTag(Int,List())))
----Or:
[source,scala]
----
inline def someGenericMapMethod[T <: Map[_,_]](map: T): String = {
val mapTag: TypeTreeTag = typeTreeTag[T]
val keyTag: TypeTreeTag = mapTag.args(0)
val valueTag: TypeTreeTag = mapTag.args(1)
s"I have been called with a Map where key is of type $keyTag and value is of type $valueTag"
}
----It can also be applied to non generic types: in such case it doesn't need to be part of a `+inline def+` but you probably can just use regular `ClassTag` then.
You can find more examples in our link:{testdir}/TestBehaviorMacro.scala[tests].