Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GenType Feature Request: Support scoped polymorphic types #6732

Open
JonoPrest opened this issue Apr 19, 2024 · 2 comments
Open

GenType Feature Request: Support scoped polymorphic types #6732

JonoPrest opened this issue Apr 19, 2024 · 2 comments

Comments

@JonoPrest
Copy link
Contributor

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.

@cometkim
Copy link
Contributor

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 (#6196)

GADT is not fully supported in the current version and improving it is definitely one of our goals :)

@JonoPrest
Copy link
Contributor Author

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 (#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 💡

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants