Get the specific simple name of a generic type in Scala

Class name can be retrieved from a Manifest (or a ClassManifest) with manifest.erasure.getName (erasure is the Class instance). For instance

def className[A : ClassManifest] = classManifest[A].erasure.getName

Edit : Seen Derek's answer, which makes this stuff with erasure.getName look rather stupid. I didn't consider toString. Still I hope what follows may be of interest

The difference between using ClassManifest and Manifest is that in the Manifest for a generic class, the type parameter are guaranteed to be available, while they are best effort in ClassManifest (compare signatures of typeParameters in both classes). The drawback of this guarantee is that a Manifest might not be implicitly available where a ClassManifest would be.

Have you considered using typeclasses instead?

trait BuilderFromMap[A] {def build(data: Map[String, String]): A} 
  // or better, return Option[A], accounting for possible failure
object User {
   implicit val Builder extends BuilderFromMap[User] {...}
}
def fromMap[A](data: Map[String, String])(implicit builder: BuilderFromMap[A])
  = builder.build(data)

This way, calls to fromMap will compile only if a Builder is available for this particular class, rather than fail with a MatchError.


For those of you coming to this question from a world with Scala 2.12.x or 2.13.x, ClassTag[T] is the preferred way to do this.

import scala.reflect._ 

trait Model 
case class User(id: String) extends Model 

def fromMap[M <: Model : ClassTag](data: Map[String, String]) = {
  val modelType = implicitly[ClassTag[M]].runtimeClass.getSimpleName
  modelType match {
    case "User" => User(data("id"))
  }
} 

val user = fromMap[User](Map("id" -> "id1"))

For Scala 2.11, following code works:

import scala.reflect.runtime.universe.{typeOf, TypeTag}

def name[T: TypeTag] = typeOf[T].typeSymbol.name.toString

def fullName[T: TypeTag] = typeOf[T].typeSymbol.fullName

Execution example:

scala> name[String]
res5: String = String

scala> fullName[String]
res6: String = java.lang.String

Ref: http://www.scala-lang.org/api/2.11.0/scala-reflect/index.html

Tags:

Generics

Scala