I\'m interested in creating a TypeTag manually (since 2.10M5):
object X {
import reflect.runtime.universe._
def tt[A : TypeTag](a: A) = typeTag[A] // how
Currently, there are three ways to create a TypeTag that supports generics manually. The first two depends on the scala-compiler, and with them you get type checking just like in compile time, as it is an actual code compilation:
import scala.reflect.runtime.universe._
import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox
val toolbox = currentMirror.mkToolBox()
def createTypeTag(tp: String): TypeTag[_] = {
val ttree = toolbox.parse(s"scala.reflect.runtime.universe.typeTag[$tp]")
toolbox.eval(ttree).asInstanceOf[TypeTag[_]]
}
If you need a serializable TypeTag and performance isn't your main concern, the first method is the most succinct. OTOH, if your use case needs to be very performant, beware that on-the-fly compilation might take a couple of seconds to finish.
The second method performs a little better:
def createTypeTag(tp: String): TypeTag[_] = {
val ttagCall = s"scala.reflect.runtime.universe.typeTag[$tp]"
val tpe = toolbox.typecheck(toolbox.parse(ttagCall), toolbox.TYPEmode).tpe.resultType.typeArgs.head
TypeTag(currentMirror, new reflect.api.TypeCreator {
def apply[U <: reflect.api.Universe with Singleton](m: reflect.api.Mirror[U]) = {
assert(m eq mirror, s"TypeTag[$tpe] defined in $mirror cannot be migrated to $m.")
tpe.asInstanceOf[U#Type]
}
}
}
This second mode creates a typed tree and fetches the concrete types marked in the TypeTag, i.e., if your target is a List[String], it will be translated to scala.collection.immutable.List[String], since scala.List is only a type alias. That's actually the behavior expected from typeTag[List[String]].
The last method is to create a Type manually and use it to create the TypeTag. This method is error-prone, there is limited type checking, and it uses internal API. This is, however, the fastest way to manually obtain a TypeTag.
def createTypeTag(tp: String): TypeTag[_] = {
val typs = // ... manipulate the string to extract type and parameters
val typSym = currentMirror.staticClass(typs[0])
val paramSym = currentMirror.staticClass(typs[1])
val tpe = universe.internal.typeRef(NoPrefix, typSym, List(paramSym.selfType))
val ttag = TypeTag(currentMirror, new TypeCreator {
override def apply[U <: Universe with Singleton](m: Mirror[U]): U#Type = {
assert(m == currentMirror, s"TypeTag[$tpe] defined in $currentMirror cannot be migrated to $m.")
tpe.asInstanceOf[U#Type]
}
})
}