GenType Feature Request: Support scoped polymorphic types
I would love to be able to build apis in rescript for users in typescript and one thing that would help is supporting scoped polymorphic types.
For example:
@genType
type rec resultOperator<'ok, 'err> = {
value: result<'ok, 'err>,
unwrap: unit => 'ok,
expect: string => 'ok,
map: 'mapped. ('ok => 'mapped) => resultOperator<'mapped, 'err>,
mapWithDefault: 'mapped. ('mapped, 'ok => 'mapped) => 'mapped,
getWithDefault: 'ok => 'ok,
isOk: unit => bool,
isError: unit => bool,
getOk: unit => option<'ok>,
getError: unit => option<'err>,
}
is generated in the typescript as:
export type resultOperator<ok, err> = {
readonly value:
| {
TAG: "Ok";
_0: ok;
}
| {
TAG: "Error";
_0: err;
};
readonly unwrap: () => ok;
readonly expect: (_1: string) => ok;
readonly map: unknown;
readonly mapWithDefault: unknown;
readonly getWithDefault: (_1: ok) => ok;
readonly isOk: () => boolean;
readonly isError: () => boolean;
readonly getOk: () => undefined | ok;
readonly getError: () => undefined | err;
};
where the scoped polymorphic types are simply "unknown".
It would be better if it could generate:
export type resultOperator<ok, err> = {
readonly value:
| {
TAG: "Ok";
_0: ok;
}
| {
TAG: "Error";
_0: err;
};
readonly unwrap: () => ok;
readonly expect: (_1: string) => ok;
readonly map: <mapped>(_1: (_1: ok) => mapped) => resultOperator<mapped, err>;
readonly mapWithDefault: <mapped>(
_1: mapped,
_2: (_1: ok) => mapped,
) => mapped;
readonly getWithDefault: (_1: ok) => ok;
readonly isOk: () => boolean;
readonly isError: () => boolean;
readonly getOk: () => undefined | ok;
readonly getError: () => undefined | err;
};
Why would I use something like this?
In ReScript it's convention to have a core generic type with a module of polymorphic functions to interop with that type. And this is nice to use with a pipe operator chaining. But if I want to allow people to chain functions in ts/js I need to model it with dot notation, so modelling types can be better done at the record level than the module level.
TIL: I never noticed that I can use GADT signature like that
I plan to completely rewrite genType as a major milestone in v12, aiming for full compatibility with the JS output (https://github.com/rescript-lang/rescript-compiler/issues/6196)
GADT is not fully supported in the current version and improving it is definitely one of our goals :)
TIL: I never noticed that I can use GADT signature like that
I plan to completely rewrite genType as a major milestone in v12, aiming for full compatibility with the JS output (https://github.com/rescript-lang/rescript-compiler/issues/6196)
GADT is not fully supported in the current version and improving it is definitely one of our goals :)
GADTs are awesome but this use case is a little simpler. I'm not sure I would want to use a GADT as typescript user where the language doesn't have it as a feature or how one would model a GADT in TS. Scoped polymorphic types already have a one to one in typescript and it would be nice to leverage that.
Awesome stuff @cometkim I'm also very happy to contribute to the genType overhaul. I've read some of the issues related to it and think declaration files are a great idea 💡