Skip to content
This repository has been archived by the owner on Nov 13, 2023. It is now read-only.

Generate opaque types corresponding to an existing Flow/TS type. #63

Closed
cristianoc opened this issue Oct 16, 2018 · 15 comments
Closed

Generate opaque types corresponding to an existing Flow/TS type. #63

cristianoc opened this issue Oct 16, 2018 · 15 comments

Comments

@cristianoc
Copy link
Collaborator

e.g.

[@genType.as "someJsType"]
type t;

would mean the type is opaque in Reason, and is seen as someJsType from JS.

Or @genType.alias or something.

@cristianoc
Copy link
Collaborator Author

Here's an example:

[@genType.import "./SomeFlowTypes"]
type anInterestingFlowType;

[@genType]
let identity = (x: anInterestingFlowType) => x;

cristianoc added a commit that referenced this issue Oct 16, 2018
- Add support for nested modules: translation of nested types and values, as well as cross references.
- [Remove deprecated way of wrapping JS components](9c38882).
- [Use strict imports for wrapping JS values and components](81c6a7f).
- [Generate opaque types corresponding to an existing Flow/TS type](#63).
@ybybzj
Copy link

ybybzj commented Oct 18, 2018

Excuse my question, how to import type from Typescript when most of them start with uppercase letter?

@ybybzj
Copy link

ybybzj commented Oct 18, 2018

And it would be much helpful if i can rename the type from TS in Reason.
for example,

// typescript file :  A.ts
export class A {
  prop: string;
  getProp(): string{
    return this.prop
  }
}

// Reason

module A = {
  
  [@genType.import "./A"]
  [@genType.as "typeof A"] //this won't work
  type t;
  [@bs.send] external getProp_: (t)=>string="getProp";
  let getProp = getProp_;
}

//then I use module A to make an utility function for ts
[@genType]
let operateA = (a: A.t) => {...} 

how can i make situation above work?

@cristianoc
Copy link
Collaborator Author

This is interesting. Would you expand on the end goal here? Extend JS class A with one more method?
Or just define a Reason function operating on A and export it to JS?

@ybybzj
Copy link

ybybzj commented Oct 18, 2018

First of all, kudos for your great work here.
I'm trying to introduce reasonml in a typescript project. I just plan to use reason to implement some utilities for ts to use, so i write a lot bindings like module A above.
Usually, i have to write ts bindings too to use reason code, and thanks to genType, now the work is much easier. But, right now i still need to use "shim" to achieve the goal, and since the binding modules are handful, so are the corresponding shim files . It would be helpful if i can just use [@genType.import] to avoid using shim files.
I'm new with this, so any suggestions would be thankful.

cristianoc added a commit that referenced this issue Oct 18, 2018
…ype.

This gets around the issue that types cannot be capitalized in Reason.

A first step towards #63.
@cristianoc cristianoc reopened this Oct 18, 2018
@cristianoc
Copy link
Collaborator Author

cristianoc commented Oct 18, 2018

@ybybzj the commit just above has a first step. The combination of @genType.import and @genType.as to import a type starting with a capital letter. (That combination was in fact planned, but not implemented yet).

The commit also shows one way to access a method of the class, which for now still does not check the type.
I'll look separately into whether it's possible to also check the type of the method.

@cristianoc
Copy link
Collaborator Author

And the example written more in the style you've used above:
93a8303

@cristianoc
Copy link
Collaborator Author

A possible future design of how to import classes, which is cleaner, is this, where one specifies only once what file the import is from, there's a convention (probably override-able) that type t maps to the type of the class, and that external functions are methods of the class.

[@genType.import "./MyMath"]
module AbsoluteValue2 = {
  type t;

  [@bs.module "./WrapJsValue"]
  external getProp: t => int = "";

  [@bs.module "./WrapJsValue"]
  external getAbs: t => int = "";
};

@ybybzj
Copy link

ybybzj commented Oct 19, 2018

thanks for the updates. I'm really fond of reasonml after trying, and gonna persuade my colleagues to use reason too, your work will make my argument much convincing.

@ybybzj
Copy link

ybybzj commented Oct 19, 2018

I've tried the commit version. There is still a little inconvenience. Since [@genType.import] only generates import statement, I can't define module A in one file, and use it in another file.
for example

// A.re
module A = {
  [@genType.import "./TS_A"]
  [@genType.as "A"]
  type t;
  ...
}

// B.re
[@genType]
let operateA = (a: A.t) => {...}

generated tsx:

// A.tsx
import {A as A_t} from './TS_A';
...

// B.tsx
const BBS = require('./B.bs');

import {A_t as A_A_t} from './A'; // here is ts error since on export type A_t

export const operateA: (_1:A_A_t) => void = BBS.operateA;

What i can do is to put genType.import in B.re instead of A.re, like this

// A.re
module A = {
  type t;
  ...
}

// B.re
[@genType.import "./TS_A"]
[@genType.as "A"]
type a = A.A.t;

[@genType]
let operateA = (a: a) => {...}

only every time i want use A.A.t in a different file, I've to declare a new local type and decorate it with [@getType.import] and [@genType.as], and explicitly annotate with the local type.

@cristianoc
Copy link
Collaborator Author

@ybybzj What's going on is that type A.t is imported, but is used by B.re as if it were exported.
Here's one way of using it from B:
1b0c53a

Not sure about how this is going to evolve, it would be nice to have a much more streamlined way of doing these things. More experimentation is required.

@ybybzj
Copy link

ybybzj commented Oct 19, 2018

Got it, thanks for the reply.

This was referenced Oct 19, 2018
cristianoc added a commit that referenced this issue Oct 21, 2018
…ules.

Principle 1 is from: #70.

This simplifies a bunch of examples.

In particular, those discusse in #63.
@cristianoc
Copy link
Collaborator Author

@ybybzj see the commit above https://github.com/cristianoc/genType/commits/master.
This should take care of the issues discussed above, minus one point: there's no current support for importing class methods (other than the usual untyped way using [@bs.send]). And that can be a separate issue: importing JS classes.

@ybybzj
Copy link

ybybzj commented Oct 23, 2018

Have tried the commit, it's good enough for me, thanks for the diligent work.

@cristianoc
Copy link
Collaborator Author

Great. Thanks a lot for the feedback.
Closing this, keeping class support for later. Tracked anyway in #70.

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

No branches or pull requests

2 participants