| Warning | (2025-05) This library served as a prototype and should not used in any real project. It is unmaintained. More robust projects (or even vanilla Scala depending on the context) exist to achieve the same. | 
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.
libraryDependencies += "io.github.gaeljw" %% "typetrees" % typetreesVersion<dependency>
  <groupId>io.github.gaeljw</groupId>
  <artifactId>typetrees_${scala.version}</artifactId>
  <version>${typetrees.version}</version>
</dependency>Two implementations are available:
- 
using implicits ( givens)
- 
using macro 
| Implementation | Pros 👍 | Cons 👎 | 
|---|---|---|
| Implicits | Easier | Only supports up to 4 generic parameters (i.e. a type  | 
| Macro | Can handle all cases | Requires to be used in  | 
import io.github.gaeljw.typetrees.TypeTree
import io.github.gaeljw.typetrees.TypeTreeTag
import scala.reflect.ClassTag
val tag: TypeTreeTag = summon[TypeTree[T]].tag // (1)
val classTag: ClassTag[_] = tag.self // (2)
val actualClass: Class[_] = classTag.runtimeClass
val typeParameters: List[TypeTreeTag] = tag.args // (3)- 
Get a TypeTreeTagfor a generic typeT
- 
Get a ClassTagfor this type
- 
Get a TypeTreeTagfor each type parameters if any
The main usage is as follows:
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:
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 tests.
import io.github.gaeljw.typetrees.TypeTreeTag
import io.github.gaeljw.typetrees.TypeTreeTagMacros.typeTreeTag
import scala.reflect.ClassTag
val tag: TypeTreeTag = typeTreeTag[T] // (1)
val classTag: ClassTag[_] = tag.self // (2)
val actualClass: Class[_] = classTag.runtimeClass
val typeParameters: List[TypeTreeTag] = tag.args // (3)- 
Get a TypeTreeTagfor a generic typeT
- 
Get a ClassTagfor this type
- 
Get a TypeTreeTagfor each type parameters if any
The main usage is as follows, within a generic inline method:
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:
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 tests.