Closed as not planned
Description
While trying to implement a local tooling pipeline, it seems that it's not quite possible to achieve the same fidelity as hand-written TypeScript definition files.
Given the following demo.res
file:
// Demo.res
@genType @ocaml.doc("A module for deciding on a subject matter for a poem.")
module DecideSubject = {
@genType.as("payload")
type payload = {
@genType.as("hint") @ocaml.doc("A hint to use as a guide when thinking of your poem.")
hint: string,
}
@genType.as("input") @ocaml.doc("The input used to generate the prompt and system prompt.")
type input
@genType.as("output") @ocaml.doc("The output from evaluating the llm prompt")
type output = {
@genType.as("text") @ocaml.doc("The text of the poem.")
text: string,
@genType.as("prompt") @ocaml.doc("The prompt used to generate the poem.")
prompt: string,
@genType.as("systemPrompt") @ocaml.doc("The system prompt used to generate the poem.")
systemPrompt: string,
}
@genType @ocaml.doc("Decide on a subject matter for a poem.")
let _placeholder = (
@ocaml.doc("The runner specification") run: string,
@ocaml.doc("The number of times to cycle through the runner") times: int,
) => (run, times)->ignore
}
We get out the the Demo.gen.tsx
file (I've elided the preamble to just show the relevant parts):
// demo.gen.tsx
// tslint:disable-next-line:interface-over-type-literal
export type DecideSubject_payload = { readonly hint: string };
export type payload = DecideSubject_payload;
// tslint:disable-next-line:max-classes-per-file
export abstract class DecideSubject_input {
protected opaque!: any;
} /* simulate opaque types */
export type input = DecideSubject_input;
// tslint:disable-next-line:interface-over-type-literal
export type DecideSubject_output = {
readonly text: string;
readonly prompt: string;
readonly systemPrompt: string;
};
export type output = DecideSubject_output;
/** Decide on a subject matter for a poem. */
export const DecideSubject__placeholder: (run: string, times: number) => void =
function (Arg1: any, Arg2: any) {
const result = Curry._2(DemoBS.DecideSubject._placeholder, Arg1, Arg2);
return result;
};
- The docstrings don't carry over for each of the fields, so the consumer of the TypeScript library doesn't get on-hover support
- The output names can't be controlled (notice the
const output: Demo.DecideSubject_output = {};
vsconst output: Demo.DecideSubject.output = {};
in the usage code below - Adding
"generatedFileExtension": ".ts"
togentypeconfig
inbsconfig.json
will output.tsx
files instead of.ts
(this could be PEBKAC) - The arguments in the
placeholder
function don't have any docstrings
Here's a screenshot of the pipeline and experience:

Separately, potentially another PEBKAC (maybe mentioned under some special TypeScript mangling rules), the output Demo.bs.js
:
// Generated by ReScript, PLEASE EDIT WITH CARE
"use strict";
function _placeholder(run, times) {}
var DecideSubject = {
_placeholder: _placeholder,
};
exports.DecideSubject = DecideSubject;
/* No side effect */
Doesn't have DecideSubject__placeholder
, but the generated types export it so it autocompletes, e.g. Demo.DecideSubject__placeholder("run", 1);