Git Product home page Git Product logo

reasonablytyped's Introduction

  $ npm install --global reasonably-typed

Converts TypeScript and Flow definitions to Reason interfaces
(Also maybe TypeScript definitions to Flow)


Take your Flow or TypeScript definition

// class.js
declare module 'classes' {
  declare type State = {
    id: number,
    storeName: string,
  }

  declare export class Store {
    constructor(initialState: State): Store;
    state: State;
    update(nextState: State): void;
  }
}

Run retyped

$ retyped class.js

Get Reason

/* Module classes */

type state = {. "id": float, "storeName": string };
module Store = {
  type t = {. "state": (state), "update": [@bs.meth](state => unit)};
  [@bs.new] [@bs.module "classes"] external make : state => t = "Store";
};

Docs

Examples

TypeScript

TypeScript has a similar workflow. Compile your TypeScript file with:

$ retyped my-definition.d.ts

Command-line Usage
Usage:
  $ retyped ...files

Examples:
  $ retyped file1.js file2.js file3.d.ts                                           [boolean]

Usage as a library ReasonablyTyped also exports a library for use! See the example below:
// lib-usage.js
import * as ReasonablyTyped from 'reasonably-typed'

const libSrc = fs.readFileSync('lib.js').toString()
const bsInterface = ReasonablyTyped.compile(libSrc)

format (code: string) => string

Formats a block of code using refmt

compile (code: string, filename?: string) => string

Compiles a libdef, formats the result, and handles errors cleanly

Development

See DEVELOPING and CONTRIBUTING.

Status

CircleCI

reasonablytyped's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reasonablytyped's Issues

Flatten union in argument

A new BuckleScript attribute is coming soon, bs.unwrap. It lets us flatted a union definition for an argument into [String string, Float float] [@bs.unwrap] instead of creating like three helpers like we do right now.

CI Builds

Right now there's no way to make a reproducible build. It would be cool if there was a CircleCI build or something

New optimizer stage: collect unused statements

If a statement is unused after some other optimizer stage, we should remove it. For example:

/* union type shim... */
external something a::[ | `String string | `Number float ] => float = "" [@bs.module "m"];

The union type shim should be removed because the union was inlined already.

Date support

We don't support built-in JS date objects! We should, and it shouldn't be too difficult.

This is mostly just adding another case to named_to_bstype and adding a new BsType, then rendering the results in bstype_to_code.

The Js.Date documentation should be helpful here too

Union type unwrap

BuckleScript introduced [@bs.unwrap] to extract a tagged type union to it's JS value. If a union type is declared directly in the args, we should use this to generate simpler code.

Use custom Flowgen

flowgen has some problems, and installs a lot of dependencies unnecessarily because it lists many development dependencies as real dependencies. flowgen2 should fix the extra dependencies problem.

Exact object types

Flow object types are "open" in Reason terms. There is a way of defining a "closed" types in Flow, using exact object types.

Thanks to @bbqbaron for bringing this up πŸ˜„

Example

declare type t = {| foo: string, bar: number |}

should transform to an closed object type:

type t = Js.t {. foo : string, bar : float};

Better CLI output

This is different than #34 because it focuses on the good part, successful output!

Right now the output is pretty simple, only shows what compiled to what and how many files were compiled:

screen shot 2017-08-14 at 10 53 16 pm

It would be nice to have some check marks or maybe emoji output for fun πŸ˜„ Maybe compilation time for each file in the output too! This is pretty open-ended, and up for discussion!

Implementation details

Basically all code for this will be in the CLI interface. No Reason experience required!

Built-in types

Flow has a lot of built in types - we should be able to do most or add not_supported warnings. We can check in named_type_to_bstype.

Better CLI errors

Here's what it looks like when the input has a syntax error:

screen shot 2017-08-14 at 10 38 50 pm

and here's what it looks like when the syntax is valid, but we can't produce output for some reason:

screen shot 2017-08-14 at 10 41 40 pm

These errors aren't friendly at all, and need to be cleaned up. A codeframe would be nice for parser errors, and when we can't generate output, a codeframe and a better explanation would be nice, as well as a link to our issue tracker πŸ˜„

Spec

  • For parser error, output a detailed syntax error and codeframe
  • For compiler errors (we can't generate output), output a codeframe and why we can't generate the code, maybe a link to our issue tracker as well

Implementation details

This should happen at the JS level, not the compiler - somewhere in the CLI code. Something like babel-code-frame would do most of what we want for us as far as output goes. There might be some Reason code necessary to extract better errors from the Flow parser, possibly in retyped_node.re or the main JS interface index.js.

As always, I'm available to help in the ReasonML Discord or on here!

Any Project to go from Reason to Flow types?

A Converter from Reason files to Flow type definition files?

This is probably out of scope for the project but I just wanted to bring it up in case there's any work already done in the area. If we run ocamlc -dtypedtree on an .mli file, it gives all the data that is generally needed to generate a flow type definition file. There are a few clever Flow tricks to make it not lossy, by using Tuple types and opaque types, but it should definitely be possible.

This project I feel like would be very useful if we want to move to a world where we can write libraries in Reason/Ocaml and generate the Javascript and also the types in Flow/Typescript.

Thoughts?

All 2.0.0 npm installs crash

The retyped command crashes when installing the 2.0.0 releases from npm.

  • ReasonablyTyped version: 2.0.0-beta4
  • bs-platform version: BuckleScript 3.1.5 (Using OCaml4.02.3+BS )
{SANDBOX} [17:39:43] /src/types/hellojs [master] > retyped index.d.ts
module.js:549
    throw err;
    ^

Error: Cannot find module './js/src/compiler'
    at Function.Module._resolveFilename (module.js:547:15)
    at Function.Module._load (module.js:474:25)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/home/nick/.npm-global/lib/node_modules/reasonably-typed/lib/index.js:2:17)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)

Duplicate types

Right now union types are converted to names types in the same scope as the declaration. This can cause an output to have a duplicate typename. This needs to be looked for and eliminated.

Example:

declare module 'test' {
  declare function add (x: number | string, y: number | string): number
}

turns into

type number_or_string = 
| Number (float)
| String (string);

type number_or_string = 
| Number (float)
| String (string);
external add : number_or_string => number_or_string => float = "" [@@bs.module "test"];

Class inheritance

Classes and interfaces cannot inherit from others right now. We should add this.

Union types don't output correctly

Union types don't output correctly at all in compiled JS - we need a new approach to remove the tag from a variant. Here's what I cam up with in the BS playground today:

type union_of_string_or_bool =
  | String of string
  | Bool of bool
    
type string_or_bool

external string_or_bool : union_of_string_or_bool -> string_or_bool = "Array.prototype.shift.call" [@@bs.val];;

type union_of_string_or_float =
  | String of string_or_bool
  | Float of float
    
type string_or_float

external string_or_float : union_of_string_or_float -> string_or_float = "Array.prototype.shift.call" [@@bs.val];;
    
external log : string_or_float -> unit = "" [@@bs.val "console.dir"];;

log (string_or_float (String (string_or_bool (Bool true))))

I'm pretty sure this could work, and it would cover all cases of union types.

Intersection types

The type A & B will combine record types in Flow, we should also support it

Better error output for parse errors

Right now the parse errors are really bad:

Error: Parse_error.Error: undefined
    at Object.compile (/usr/local/lib/node_modules/reasonably-typed/lib/index.js:45:11)
    at fs.readFile (/usr/local/lib/node_modules/reasonably-typed/lib/cli.js:86:40)
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:503:3)

We should make this better. I'm thinking something like the codeframe errors we do now for Modulegen errors.

Typescript definition file extension included in bs.module name

If we run on a typescript file called "simple.d.ts":

declare function add(x: number, y: number): number

the output is

[@bs.module "simple.d.ts"] external add : (~x:float) => (~y:float) => float = "";

while it should start with [@bs.module "simple"].

  • ReasonablyTyped version: 0.13.0 (current master 8338e63)
  • bs-platform version: BuckleScript 2.2.2 (Using OCaml4.02.3+BS )

Run output through Refmt

There is one idiomatic style for Reason code - Refmt. The output should be run through this automatically. It would also help identify when we cause a syntax error.

How exactly do I convert this file with retyped?

Basically, I dont know what I'm missing in the docs so I will provide examples below.

Lets say I want to use retyped to create type for a react-apollo Query

Trying retyped on the above, i get:

PrisBook:react-apollo$[develop !] retyped Query.d.ts
Error: Parse_error.Error: undefined
    at Object.compile (/Users/prisc_000/.config/yarn/global/node_modules/reasonably-typed/lib/index.js:60:11)
    at fs.readFile (/Users/prisc_000/.config/yarn/global/node_modules/reasonably-typed/lib/cli.js:56:40)
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:528:3)
PrisBook:react-apollo$[develop !]

Trying on Query.js i get:

PrisBook:react-apollo$[develop !] retyped Query.js

✘  Unknown statement type when parsing libdef [in Query.js from 1:0 to 10:5]

> 1 | var __extends = (this && this.__extends) || (function () {
  2 |     var extendStatics = Object.setPrototypeOf ||
  3 |         ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  4 |         function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };


Compiled 0 file
There were errors with 1 file

PrisBook:$ retyped --version
0.13.0
PrisBook:
$ bsc -version
BuckleScript 2.2.3 (Using OCaml4.02.3+BS )
PrisBook:~$

Thank you.

React Components

ReasonablyTyped should special-case things that extends the React component class and adapt them to use the Reason React API.

featured flow example in readme does not work

This example in the README does not work.

// class.js
declare module 'classes' {
  declare type State = {
    id: number,
    storeName: string,
  }

  declare export class Store {
    constructor(initialState: State): Store;
    state: State;
    update(nextState: State): void;
  }
}

Running retyped on it produces a file t.re containing only

y

I ran this because I was trying to update the example to Reason 3 syntax, but this will need to be fixed first or changed to something that will compile.

  • ReasonablyTyped version: 0.13.0 (master cca6577)
  • bs-platform version: BuckleScript 2.2.2 (Using OCaml4.02.3+BS )

Spread parameters

Rest spread parameters are not yet supported:

declare function add(...nums): number

String literal seems cause syntax error

When ReasonablyTyped attempt to convert code includes string literal, it generates incorrect syntax

Input

declare module 'literal-type' {
  declare export function f(x: "a" | "b"): void;
}

Output

[@bs.module "literal-type"] external f : (~x:([`a | `b] [@bs.string])) => unit = "";

Probably we expect

[@bs.module "literal-type"] external f : (~x:([@bs.string] [`a | `b])) => unit = "";
  • ReasonablyTyped version: (output of retyped --version)

0.13.0 (build from source code manually)

  • bs-platform version: (output of bsc -version)

BuckleScript 2.2.2 (Using OCaml4.02.3+BS )

Render Flow object types as open

While researching #19, I wonder if there's an upstream change we need to make. We render Flow object types as closed Reason objects, but I think they're supposed to be open, aren't they?

Right now, test object-type:

declare type subscribeOptions = {
  start: number,
  stop: number
}

becomes

type subscribeOptions = Js.t {. start : float, stop : float};

However, Flow permits extra fields in object types that aren't exact. For example, function foo(x: SubscribeOptions) should accept objects with more than just start and stop on them.

Should we produce instead Js.t {.. start: float, stop: float } unless the type is declared with {| |}?

Update Test Expectations?

I think this commit introduced a number of compiler test failures. Not sure of background, but I thought I'd at least register it. Since the commit message was Stop union types in parameters from generating precode, perhaps the fixtures are just out of date?

E.g. duplicate-type-params seems to have dropped:

type union_of_number_or_string =
  | Number float
  | String string;

type number_or_string;

external number_or_string : union_of_number_or_string => number_or_string =
  "Array.prototype.shift.call" [@@bs.val];

Progress on v2

First of all - amazing project πŸŽ‰Making it solid and robust will allow Reason community to grow very rapidly, allowing adoption in many existing projects. Thank you for all your work!

I want to integrate Reason into my current React (with flow) project. The main obstacle is creating bindings to components library. It's around 30 components I have to creating bindings for so nothing huge to do manually but it would be better to create automated solution.

I was playing with current version and the initial output is good but have to be updated manually to latest ReasonReact/Reason/Bucklescript version. I saw there is 2 folder with experimental branch with the new compiler so I started playing with it. It's very early stage and it's missing a lot of features yet.

Some stuff I was improving baransu@c3e3477#diff-ad87cfcd8f69e5ca9743bdb78cc3bf81 but not sure if it's good direction.

Could you create some small tasks to grab and work on in free time? I really want to contribute but having no guidelines nor roadmap for version 2 doesn't help.

String literal union

Types of the form 'one' | 'two' | 'three' are pretty common, and have special treatment in BuckleScript with bs.as string. We should detect these, flatted when the happen in an alias or some other way, and then render them as such.

Run retyped against node_modules/@types

FlowTyped puts all definitions in the flow-typed directory, and we have a CLI flag to run against those files automatically. It would be cool if we could do the same for TypeScript types installed with npm/yarn. These files are dumped in node_modules/@types.

See the CLI code for FlowTyped for more information about how to add this feature. The yargs documentation should also be pretty helpful.

FlowTyped Mega Issue

Heres a list of the most common issues when compiling libraries from FlowTyped:

34  Exists type is not currently supported 
20  Type parameter bounds is not currently supported 
18 SYNTAX ERROR
17  Intersection types is not currently supported 
16  Import statements is not currently supported 
15  Unknown declaration when converting a module property declaration 
13  static CallProperty on Object types is not currently supported 
12  Indexer on Object types is not currently supported 
10  Inheriting in interfaces is not currently supported 
9  Unknown declaration type when converting a module declaration 
7  Cannot use string literal outside the context of a union type
7  Typeof can only operate on variable declarations
5  Inheritance not supported
4  Built-in type $Exports is not currently supported 
3  React components is not currently supported 
3  Class declatations is not currently supported 
3  Built-in type $Subtype is not currently supported 
2  Unknown identifier
2  Built-in type $Shape is not currently supported 
2  Type parameter variance is not currently supported 
1  undefined
1  Built-in type $PropertyType is not currently supported 
1  typeof can only operate on classes

Starting from the top these are the biggest problems we face right now.

How to generate this report: npm run test:collect && node docs/find-error.js

Type parameters

Couple places they can be used:

  • Function declarations
  • Method declarations
  • Class declarations
  • Interface declarations

Not_found

Hello,

I am trying to convert react-navigation from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-navigation but I get this output

[ 'Not_found', -6, tag: 248 ]
Error: N
    at Object.compile (/Users/laibulle/ReasonablyTyped/lib/index.js:56:11)
    at fs.readFile (/Users/laibulle/ReasonablyTyped/lib/cli.js:61:40)
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:532:3)
  • ReasonablyTyped version: 0.13.0 but actually it is from master
  • bs-platform version: BuckleScript 3.0.0 (Using OCaml4.02.3+BS )

DefinitelyTyped test suite

We currently have a test suite running against FlowTyped, but it would be great if we also had one to run against DefinitelyTyped.

See the FlowTyped test runner for more information about how to implement this one. We might have to include DefinitelyTyped as a git submodule.

Syntax error when using for typescript definitions

Description

Tried running retyped compile for raven-js typescript definitions resulting in the following error.

retyped compile node_modules/raven-js/typescript/raven.d.ts
Error: File "", line 49, characters 29-36:
313: <SYNTAX ERROR>

    at Object.compile (/usr/local/lib/node_modules/reasonably-typed/lib/index.js:49:11)
    at fs.readFile.e (/usr/local/lib/node_modules/reasonably-typed/lib/cli.js:86:40)
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:446:3)

Step to reproduce

  • install retyped 0.11.0
  • install bs-platform 1.9.1
  • yarn add -E [email protected]
  • retyped compile node_modules/raven-js/typescript/raven.d.ts

Setup details

retyped --version
0.11.0
bsc -version
BuckleScript 1.9.1 (Using OCaml4.02.3+BS )

If you need more details you can ping me on Discord (@arnar) or this issue πŸ‘

Multiple modules

Handle cases like:

declare module 'test/one' {
  // ...
}

declare module 'test/two' {
  // ...
}

Right now we get the name from the first module and flatten declarations.

Import statements

We should process import statements to be modules.

Spec

If there is a known binding in reasonml-community, transform the import into aliasing from that. Error on absolute imports without known modules.

For relative imports, use our own module transforming logic and assumer ReasonablyTyped will also process it.

For example, with the statement:

import type { $Request } from 'express'

we should look at the express bindings and emit:

type request = Express.Request.t

based on the following code: https://github.com/reasonml-community/bs-express/blob/master/src/express.re#L21-L22

For a local import such as:

import type { myThing } from './thing'

should be transformed to:

type myThing = Thing.myThing

Implementation details

You'll probably need to match on import statements in statement_to_program, and create a new BsDecl variant, then finally the output in declaration_to_code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.