@@ -153,6 +153,117 @@ let () =
153
153
> * [ JavaScript compilation in dune] ( https://dune.readthedocs.io/en/latest/jsoo.html )
154
154
> * [ ` gen_js_api ` ] ( https://github.com/LexiFi/gen_js_api/blob/master/INSTALL_AND_USE.md )
155
155
156
+ ## Handling ` import ` and ` export `
157
+
158
+ To work with multiple files and packages, ts2ocaml has some conventions around the name of the generated OCaml source codes.
159
+
160
+ 1 . If not known, ts2ocaml computes the JS module name of the input ` .d.ts ` file by [ heuristics] ( #how-the-heuristics-work ) .
161
+ 2 . ts2ocaml converts the JS module name to a OCaml module name by the followings:
162
+ - Removes ` @ ` at the top of the module name
163
+ - Replaces ` / ` with ` __ `
164
+ - Replaces any other signs (such as ` - ` ) to ` _ `
165
+ 3 . ts2ocaml uses the OCaml module name as the output file name.
166
+
167
+ ### How the heuristics work
168
+
169
+ * If the filename is equal to ` types ` or ` typings ` of ` package.json ` , then ts2ocaml will use the package name itself.
170
+ - input: ` node_modules/typescript/lib/typescript.d.ts `
171
+ - ` package.json ` : ` "typings": "./lib/typescript.d.ts", `
172
+ - ` getJsModuleName ` : ` typescript `
173
+ - output file: ` typescript.mli `
174
+ * If the filename is present in ` exports ` of ` package.json ` , then ts2ocaml will combine the package name and the exported module name.
175
+ - input: ` node_modules/@angular/common/http/http.d.ts `
176
+ - ` package.json ` : ` "exports": { .., "./http": { "types": "./http/http.d.ts", .. }, .. } `
177
+ - ` getJsModuleName ` : ` @angualr/common/http `
178
+ - output file: ` angular__common__http.mli `
179
+ * Otherwise, ts2ocaml uses a heuristic module name: it will combine the package name and the filename. ` index.d.ts ` is handled specially.
180
+ - input: ` node_modules/cassandra-driver/lib/auth/index.d.ts `
181
+ - ` getJsModuleName ` : ` cassandra-driver/auth `
182
+ - output file: ` cassandra_driver__auth.mli `
183
+ - if ` package.json ` is not present, the package name is also inferred heuristically from the filename.
184
+
185
+ ### How the ` import ` statements are translated
186
+
187
+ * ` import ` of another package from ` node_modules ` will be converted to an ` open ` statement or a module alias.
188
+ - The OCaml module name of the imported package is computed by the step 2 of [ the above] ( #handling-import-and-export ) .
189
+
190
+ ``` typescript
191
+ // node_modules/@types/react/index.d.ts
192
+ import * as CSS from ' csstype' ;
193
+ import { Interaction as SchedulerInteraction } from ' scheduler/tracing' ;
194
+ ...
195
+ ```
196
+ ``` ocaml
197
+ (* react.mli *)
198
+ module CSS = Csstype.Export
199
+ module SchedulerInteraction = Scheduler__tracing.Export.Interaction
200
+ ...
201
+ ```
202
+
203
+ * ` import ` of relative path will be converted to an ` open ` statement or a module alias.
204
+ - The OCaml module name of the imported file will also be inferred by [ heuristics] ( #how-the-heuristics-work ) .
205
+ ``` typescript
206
+ // node_modules/cassandra-driver/index.d.ts
207
+ import { auth } from ' ./lib/auth' ;
208
+ ```
209
+
210
+ ``` ocaml
211
+ (* cassandra_driver.mli *)
212
+ module Auth = Cassandra_driver__auth.Export.Auth
213
+ ```
214
+
215
+ ``` typescript
216
+ // node_modules/cassandra-driver/lib/mapping/index.d.ts
217
+ import { Client } from ' ../../' ;
218
+ ```
219
+
220
+ ``` ocaml
221
+ (* cassandra_driver__mapping.mli *)
222
+ module Client = Cassandra_driver.Export.Client
223
+ ```
224
+
225
+ * Indirect ` import ` using identifiers is not yet be supported.
226
+
227
+ ``` typescript
228
+ import { types } from ' ./lib/types' ;
229
+ import Uuid = types .Uuid ; // we should be able to convert this to `module Uuid = Type.Uuid`, but not yet
230
+ ```
231
+
232
+ * Direct ` export ` of an external module ** will not be supported** .
233
+
234
+ ``` typescript
235
+ export { someFunction } from ' ./lib/functions' ; // this is VERY hard to do in OCaml!
236
+ ```
237
+
238
+ ### How the ` export ` statements are translated
239
+
240
+ ts2ocaml will create a module named ` Export ` to represent the exported definitions.
241
+
242
+ * If an export assignment ` export = Something ` is used, the ` Export ` module will be an alias to the ` Something ` module.
243
+ ``` ocaml
244
+ (* export = Something *)
245
+ module Export = Something
246
+ ```
247
+
248
+ * If ES6 exports ` export interface Foo ` or ` export { Bar } ` are used, the ` Export ` module will contain the exported modules.
249
+ ``` ocaml
250
+ module Export : sig
251
+ (* export interface Foo *)
252
+ module Foo = Foo
253
+ (* export { Bar } *)
254
+ module Bar = Bar
255
+ (* export { Baz as Buzz } *)
256
+ module Buzz = Baz
257
+ end
258
+ ```
259
+
260
+ This is why you are advised to use the generated bindings with the following:
261
+
262
+ ``` ocaml
263
+ (* This is analogous to `import * as TypeScript from "typescript";` *)
264
+ module TypeScript = Typescript.Export
265
+ ```
266
+
156
267
# Usage
157
268
158
269
``` bash
0 commit comments