Nameof operator

Does ReScript have the concept of a nameof operator? Example in F#: Nameof - F# | Microsoft Learn

Something that can print the current value or field name of a symbol.

I’m my code I need to do something like:

type order = {
  isProcessed: bool,
  contact: contactPerson,
  created: milliseconds,
  tickets: array<ticket>,
  food: foodCount,
}

await orderSnapshot->update_field("isProcessed", true)

To update a single value in my Firebase database, I need to pass the name of my field as a string.
It would be great if I could do something like await orderSnapshot->update_field(nameof(isProcessed), true)

Does something like this exist?

There’s no such operator in rescript. You can build a runtime helper for this using proxy:

await orderSnapshot->update_field(o => o.isProcessed, true)

Where o is a proxy used to track which field is accessed. Also, this way, you can infer the value type.

1 Like

What would that proxy look like?

I’m talking about javascript proxy with get trap

So something along these lines:

const handler = {
  get: function (target, property, receiver) {
    return property;
  },
};

let nameof = (instance, getProperty) => {
  const p = new Proxy(instance, handler);
  return getProperty(p);
};

// Example property access
let y = { bar: 3 }
console.log(nameof(y, (y) => y.bar));

?

That’s very clever, had never thought of that.

I don’t remember the exact API. Looks like the code won’t work correctly, but this is what I meant :+1:

I like hacky solutions like this :joy:

2 Likes

This works for me: ReScript Playground

3 Likes

Some time later, I’m not super excited anymore about this solution. My nameof operator, it always needs a type annotation like nameof((o: Domain.Firebase.order) => o.isProcessed) and I don’t find it very ergonomic.

I’m wondering if ppx would not be convenient to generate string constants of my fields instead.

%something
type foo = {
   x: int,
   y: string,
   bar: array<string>
}

and generate

// Not sure about casing, but you get the idea
module FooKeys = {
   let X = "x"
   let Y = "y"
   let BAR = "bar"
}

Would such a PPX thing be possible in ReScript? I would guess, AST wise it is not that hard to construct.

I can understand this. Accessing by keys rarely happens in pure ReScript code, but is useful when interacting with external JS codes.

I used this pattenrs a lot

type key =
  | @as("preferred_language") PreferredLanguage
  | @as("preferred_timezone") PreferredTimeZone

@genType
module Key = {
  let \"PreferredLanguage" = PreferredLanguage
  let \"PreferredTimeZone" = PreferredTimeZone
}

Used it for building DTOs

There may some community PPXs exist already. e.g. GitHub - Astrocoders/lenses-ppx: GADT lenses

But generalizing it with using PPX or Proxies seems like an overkill solution. What it really need is more of a simple record ↔ dict converter.