Search code examples
scalatypesclassnamescala-reflect

How to get generic simple class name from scala TypeTag?


How can I get the simple class name including generic using TypeTag? I think that the method signature should be like:

def getClassName[A: TypeTag](a: A): String

getClassName(Map("a" -> 123)) should return Map[String,Int].


Things I've tried:

def getClassName[A: TypeTag](a: A): String = {
  typeOf[A].typeSymbol.name.toString
}

scala> getClassName(Map("a" -> 123))
res1: String = Map
def getClassName[A: TypeTag](a: A): String = {
  typeOf[A].typeSymbol.toString
}

scala> getClassName(Map("a" -> 123))
res1: String = trait Map
def getClassName[A: TypeTag](a: A): String = {
  typeOf[A].toString
}

scala> getClassName(Map("a" -> 123))
res1: String = scala.collection.immutable.Map[String,Int] // It knows the full type!
def getClassName[A: TypeTag](a: A): String = {
  typeOf[A].typeSymbol.fullName
}

scala> getClassName(Map("a" -> 123))
res1: String = scala.collection.immutable.Map

Solution

  • From here: https://docs.scala-lang.org/overviews/reflection/typetags-manifests.html

    import scala.reflect.runtime.universe._
    
    def getClassName[T](x: T)(implicit tag: TypeTag[T]): String = {
        tag.tpe match { case TypeRef(_, t, args) => s"""${t.name} [${args.mkString(",")}]""" }
    }
    
    getClassName(Map("a" -> 123))
    
    res5: String = Map [java.lang.String,Int]
    

    UPDATE: Shorter version with full class names

     def getClassName[T: TypeTag](x: T) = typeOf[T].toString
    
    getClassName(Map("a" -> 123))
    res1: String = scala.collection.immutable.Map[java.lang.String,Int]