I took the example from the announcement blog post:
module A = struct
[%%private let a = 3]
let b = 4
end
And attempted to expand it to the entire module definition:
[%%private module A = struct
[%%private let a = 3]
let b = 4
end]
Reason even has syntax support for this, judging by what happens on https://reasonml.github.io/en/try, but the website comes back with Uninterpreted extension 'private'. (in my project the compiler is reporting the structure is not supported in local extension).
I have started using local modules to namespace types and externals, so as a result I end up with a lot of var A = {} in my generated JS which cannot be removed with tree shaking (I may eventually add interface files but that would be inconvenient at the moment). Having private support would be a big help!
there are some subtlety to support private modules since types in modules may be escaped, but we will revisit later
Just to elaborate a bit on the original post, having %private type would also be great (not sure how hard it'd be):
type%private t = ...;
// Additionally to
module%private X = ...;
Also (on a slightly different note), I find myself using opaque types quite often, and having to write an interface file just for that is rather unergonomic:
type t = int;
let whatever: t => string = ...;
// and in the interface file
type t;
let whatever: t => string;
Would there be a way to have an %opaque "modifier"?
type%opaque t = int;
So that t is exported as t, not as t = int.
I don't agree with extending private to types. The feature is not designed to _replace_ interface files, just make a few simple cases easier to develop without them.
Abstract t is the big use case for having an interface file; this way the implementation doesn't need to know or care that the exported type is abstract.
I don't find it unergonomic at all, but I've been writing Reason/OCaml for 6 years so I am very much used to it. I also _never_ use local type annotations in implementations unless the compiler forces me to, which is another habit I see coming from TypeScript developers a lot (understandably, due to how TS type inference works). This is another practice that interface files help with; there is no need for local annotations to prevent accidentally changing the function type.
we will revisit this when we upgrade compiler upstream
@bobzhang if you upgrade to 4.08+ upstream then this issue will become moot due to open struct ... end functionality. E.g.
open struct
module A = struct
let a = 3
let b = 4
end
end
let () = print_int (A.a + A.b)
Most helpful comment
there are some subtlety to support
private modulessince types in modules may be escaped, but we will revisit later