:diamond_shape_with_a_dot_inside: Converts Flow and TypeScript definitions to Reason interfaces
This whole release was done by @cristianoc in #46!
Output should now be in Reason 3 syntax 😄 Check out how awesome this output is!
type thing('x) = {. "lst": array('x)};
module Adder = {
type t('x) = {. "add": [@bs.meth] ('x => 'x)};
[@bs.new] [@bs.module "generics"] external make : 'x => t('x) = "Adder";
};
type subOpts('m, 'n) = {. "m": 'm, "n": Adder.t('n)};
The old syntax won't be supported past this point.
See more in #46
Super short example, but this works now 😄
import type { Component } from 'react'
declare module 'react-component' {
declare type props = { input?: string, b?: boolean }
declare export class ReactComponent extends Component<props> {}
}
gets compiled to
type props = {. "input": Js.Nullable.t(string), "b": Js.Nullable.t(Js.boolean)};
module ReactComponent = {
[@bs.module "react-component"] external reactcomponent_reactComponent : ReasonReact.reactClass =
"ReactComponent";
let make = (~input=?, ~b=?, children) => {
let props: props = {
"input": Js.Nullable.from_opt(input),
"b": Js.Nullable.bind(Js.Nullable.from_opt(b), [@bs] ((x) => Js.Boolean.to_js_boolean(x)))
};
ReasonReact.wrapJsForReason(~reactClass=reactcomponent_reactComponent, ~props, children)
};
};
Local imports should work exactly how you expect them to 🙂 Absolute imports will get namespaces with the capital module name
It's pretty common in JS to use the following pattern:
declare function add(a: string | number, b: string | number): string
Before this release we would generate a helper type for the union, which was eliminated at runtime. Since then BuckleScript released @bs.unwrap
, allowing us to produce the following output:
external add :
a::[ | `String string | `Number float] [@bs.unwrap] =>
b::[ | `String string | `Number float] [@bs.unwrap] =>
string =
"" [@@bs.module "module"];
And the callsite comes pretty naturally! It looks like:
let result = add (`String "hello") (`Number 3.);
Unions of string literals also get processed as @bs.string
now, making them typesafe (tm):
declare function apply(input: 'add' | 'subtract'): number
external apply :
input::([`add | `subtract] [@bs.string]) =>
float =
"" [@@bs.module "module"];
Union declarations will also get inlined too!
With the input:
declare module 'module' {
declare type input = number | string
declare function apply(input: input): number
}
You'll get something like:
external apply :
input::([`Number float | `String string] [@bs.unwrap]) =>
float =
"" [@@bs.module "module"];
This should make the API's for a lot more JS libraries easier to use and closer to what JS users would expect.
This is a pretty big release for ReasonablyTyped, it marks a huge step towards converting many FlowTyped libraries and our first external contributor! Here's what we built in the past few weeks:
ReasonablyTyped can now compile classes, interfaces and types that have type parameters! For example, consider the following class:
declare class Test<M> {
constructor<T>(init: T): Test<T>,
add<N>(value: N): M
}
ReasonabyTyped can now turn that into:
module Test = {
type t 'm = Js.t {. add: 'n . ('n => 'm ) [@bs.meth]};
external make : 't => t 't = "Test" [@@bs.new] [@@bs.module "generics"];
};
Also note the new code generation for classes! We use the convention on creating a module with a
type named t
and export a function called make
to create that type.
It can be common to see a Flow definition like:
declare module "multiple-modules" {
declare export function someTopLevel(): void
}
declare module 'multiple-modules/first' {
declare export function first(): number
declare export function second(): void
}
declare module 'multiple-modules/second' {
declare export function second(): string
declare export function third(): void
}
declare module 'multiple-modules/third' {
declare export function third(): string
declare export function fourth(): void
}
declare module 'multiple-modules/third/inner' {
declare export function third(): string
declare export function fourth(): void
}
which declares modules for it's nested files and directories in the same definition, but still all for the same package. We now take care of these in a smart way and recognize that they're submodules. The above would produce:
external someTopLevel : unit => unit = "" [@@bs.module "multiple-modules"];
module First = {
external first : unit => float = "" [@@bs.module "multiple-modules/first"];
external second : unit => unit = "" [@@bs.module "multiple-modules/first"];
};
module Second = {
external second : unit => string = "" [@@bs.module "multiple-modules/second"];
external third : unit => unit = "" [@@bs.module "multiple-modules/second"];
};
module Third = {
external third : unit => string = "" [@@bs.module "multiple-modules/third"];
external fourth : unit => unit = "" [@@bs.module "multiple-modules/third"];
};
module ThirdInner = {
external third : unit => string = "" [@@bs.module "multiple-modules/third/inner"];
external fourth : unit => unit = "" [@@bs.module "multiple-modules/third/inner"];
};
Shoutout to @bbqbaron for the huge contribution here!
TypeScript support is here! Pass any file to ReasonablyTyped with the extension .d.ts
and the TypeScript compilation mode will be used! Note that TypeScript support is still in it's early stages, and might now always produce output. With that said, here's an example!
declare module 'numbers' {
export var xfg: number
export function add(
a: number,
b: number
): number
}
compiles to
external xfg : float = "" [@@bs.module "numbers"];
external add : a::float => b::float => float = "" [@@bs.module "numbers"];
ReasonablyTyped also supports modules with names determined by their filename, as is often seen in DefinitelyTyped.
Previously there was a build system in place that depended on Make and rebuild command manually to compile. This system was non-standard and didn't manage libraries or anything like that for you. Now we're using ReasonNativeProject as the basis for our build, sprinkled in with some JSOO goodness.
Array<$type>
is now processed as an arrayinterface { (x: number): number }
)declare var exports: typeof MyClass
)