Retrieve type of a NamedTuple field

Given a set of fields obtained through NamedTuple.From, is it possible to retrieve the type of a named field through a type application?

I’m looking for something along lines of:

case class Person(name: String, age: Int)

type Fields = NamedTuple.From[Person]

type AgeField = Fields.Named["age"] // how do I do this?

thanks!

Best thing I could come up with is the following:

First, define a type for “index of” to obtain the index of a type within a tuple:

import scala.compiletime.ops.int.S

type IndexOfImpl[T <: Tuple, Elem, I <: Int] <: Int = T match
  case EmptyTuple => -1
  case Elem *: _ => I
  case _ *: tail => IndexOfImpl[tail, Elem, S[I]]

type IndexOf[T <: Tuple, Elem] = IndexOfImpl[T, Elem, 0]

Then, define a type for “field by name” that uses IndexOf to obtain the index of the name (from NamedTuple.Names) and then uses NamedTuple.Elem to obtain the type of the value at that index:

import scala.NamedTuple.AnyNamedTuple

type FieldByName[T <: AnyNamedTuple, Name <: String] =
  NamedTuple.Elem[T, IndexOf[NamedTuple.Names[T], Name]]

With that, you can now do:

type AgeField = FieldByName[Fields, "age"]

val x: AgeField = 9

Found another approach that works as well - just obtain the names and field-types as separate types of Tuples and iterate through those:

import scala.NamedTuple.AnyNamedTuple

type FieldByNameImpl[Names <: Tuple, Fields <: Tuple, Name] = (Names, Fields) match
  case (Name *: _, field *: _) => field
  case (_ *: nTail, _ *: fTail) => FieldByNameImpl[nTail, fTail, Name]

type FieldByName[T <: AnyNamedTuple, Name <: String] =
  FieldByNameImpl[NamedTuple.Names[T], NamedTuple.DropNames[T], Name]
1 Like

Nice, thank you for sharing this.

I also made progress independently but got stuck when trying to obtain a ClassTag inside my inline def.

Details here:

Oddly, it works if you do not declare an intermediate type Fields and rather define FieldTpe in one line:

1 Like

Huh, interesting. Good find. Thank you again, this unblocks me!