Module improperly exporting JS reserved keyword

Client.res I’m running into an issue where exporting a delete function (valid in ReScript) is causing an issue in the compiled JS module -

…
@gentype
let delete = async (client: t, url: string) => {
  await fetch(
    url,
    {
      method: #DELETE,
      headers: headers(client)
    },
  )
}

Client.bs.js my function is being exported as $$delete without being properly aliased -

async function $$delete(client, url) {
  return await $$fetch$1(url, {
              method: "DELETE",
              headers: Caml_option.some(new Headers(Belt_MapString.toArray(client.headers)))
            });
}

export {
  … ,
  $$delete , // ❌ should be export { $$delete as delete }
}

Using delete in this way should be a non-issue because the library consumer has two choices -

import * as Client from "mymodule/client"
Client.delete(…) // ✅ valid

import { delete as delete_ } from "mymodule/client"
delete_(…) // ✅ valid

The situation is worsened when you consider the Client.gen.tsx -

// ❌ invalid `const delete` reserved keyword
export const delete: (client:t, url:string) => Promise<Js_Json_t> = function (Arg1: any, Arg2: any) {
  const result = Curry._2(ClientBS.delete, Arg1, Arg2); // ❌ ClientBs exports $$delete
  return result
};

ClientBS.delete is ironically valid JS however the actual export is ClientBS.$$delete. I would expect gentype to do something like -

// ✅ expected `const $$delete …`
const $$delete: (client:t, url:string) => Promise<Js_Json_t> = function (Arg1: any, Arg2: any) {
  const result = Curry._2(ClientBS.delete, Arg1, Arg2);
  return result
};

export { $$delete as delete } // ✅ expected

At first I tried working around this using @gentype.as("delete_") which fixes the TS error, however the generated function still accesses the incorrect export from the generated JS -

// ✅ valid `const delete_`
export const delete_: (client:t, url:string) => Promise<Js_Json_t> = function (Arg1: any, Arg2: any) {
  const result = Curry._2(ClientBS.delete, Arg1, Arg2); // ❌ ClientBS exports $$delete only
  return result
};

My current solution is to export delete_ instead. This does not meet the API requirement but that’s a problem I’ll have to solve another day.

…
@gentype
let delete_ = async (client: t, url: string) => {
  …
}

I found this thread which is related -

This is exactly the case for me, however the “solution” provided is just to avoid the listed identifiers. Considering export { $$delete as delete } is completely valid, I should think ReScript has a way to do this. The design requirements of the library are not always set by the developer.

After checking this briefly, it does sound like just adding an aliasing export in addition to the mangled export should be fine. Although it’d need more investigation. In that case, it’d be:

export {
  $$delete,
  $$delete as delete
}

This would leave the $$ export as-is though, because the compiler uses that internally. One could look into if it’s possible to get rid of all $$ exports as well in favor of only the aliased “proper” names.