Skip to content
Anjunar/ DOCS

Generics

A generic class keeps its type parameters with their bounds, and an applied type keeps its arguments. Both are visible in Scala.js, where the JVM's generic signatures do not exist.

Parameters

Type variables with bounds

typeParameters holds a TypeVariableDescriptor per parameter; its bounds are the names of its upper bounds.

E
scala.Nothing, demo.Entity
K
scala.Nothing, scala.Any
scala
trait Entity { def id: String } class Repository[E <: Entity, K](val name: String) ReflectMacros.reflect[Repository[?, ?]].typeParameters.collect { case variable: TypeVariableDescriptor => variable.name -> variable.bounds.toList }
Arguments

Applied types

reflectType of an applied type returns a ParameterizedTypeDescriptor. Its rawType is the ClassDescriptor, its typeArguments the arguments in order.

reflectType[Map[String, List[Int]]].typeName
scala.collection.immutable.Map[java.lang.String, scala.collection.immutable.List[scala.Int]]
typeArguments(1).typeName
scala.collection.immutable.List[scala.Int]
scala
ReflectMacros.reflectType[Map[String, List[Int]]] match case parameterized: ParameterizedTypeDescriptor => parameterized.typeArguments(1) // itself parameterized: List[Int] case other => other
Properties

Generic property types

A property's propertyType is a TypeDescriptor too, so a List[String] field tells you its element type.

reflect[Box[?]].getProperty("value").map(_.propertyType.typeName)
Some(T)
Parameters stay parameters

The descriptor of a generic class describes its declaration: a property of type T says T. Reflect the applied type with reflectType when you need the argument.