@@ -143,7 +143,8 @@ let emit_code_item ~config ~emitters ~module_items_emitter ~env ~file_name
143
143
Log_. item " Code Item: %s\n "
144
144
(code_item |> code_item_to_string ~config ~type_name_is_interface );
145
145
match code_item with
146
- | ImportValue {as_path; import_annotation; type_; value_name} ->
146
+ | ImportValue {as_path; import_annotation; type_; value_name; export_binding}
147
+ ->
147
148
let import_path = import_annotation.import_path in
148
149
let first_name_in_path, rest_of_path =
149
150
match value_name = as_path with
@@ -163,8 +164,15 @@ let emit_code_item ~config ~emitters ~module_items_emitter ~env ~file_name
163
164
in
164
165
(emitters, value_name_not_checked, env)
165
166
in
166
- let type_ =
167
+ (* Extract potential satisfies wrapper to drive custom emission. *)
168
+ let satisfies_rescript_type_opt =
167
169
match type_ with
170
+ | Ident {builtin = _; name; type_args = [rescript_t; _]}
171
+ when SatisfiesHelpers. is_helper_ident name -> Some rescript_t
172
+ | _ -> None
173
+ in
174
+ let adjust_for_function_component t =
175
+ match t with
168
176
| Function
169
177
({
170
178
arg_types = [{a_type = Object (closed_flag, fields); a_name}];
@@ -217,44 +225,81 @@ let emit_code_item ~config ~emitters ~module_items_emitter ~env ~file_name
217
225
}
218
226
in
219
227
Function function_
220
- | _ -> type_)
221
- | _ -> type_
228
+ | _ -> t)
229
+ | _ -> t
230
+ in
231
+ let type_for_emit = adjust_for_function_component type_ in
232
+ let value_name_type_checked =
233
+ let base = value_name ^ " TypeChecked" in
234
+ match export_binding with
235
+ | false -> " _" ^ base
236
+ | true -> base
222
237
in
223
- let value_name_type_checked = value_name ^ " TypeChecked" in
224
238
let emitters =
225
- imported_as_name ^ rest_of_path
226
- |> EmitType. emit_export_const ~config
227
- ~comment:
228
- (" In case of type error, check the type of '" ^ value_name
229
- ^ " ' in '"
230
- ^ (file_name |> ModuleName. to_string)
231
- ^ " .res'" ^ " and '"
232
- ^ (import_path |> ImportPath. emit)
233
- ^ " '." )
234
- ~early: true ~emitters ~name: value_name_type_checked ~type_
235
- ~type_name_is_interface
239
+ match satisfies_rescript_type_opt with
240
+ | Some rescript_type ->
241
+ let rescript_type = adjust_for_function_component rescript_type in
242
+ let expr = imported_as_name ^ rest_of_path in
243
+ (* Non-exported const for the checked binding, emitted early for ordering. *)
244
+ let comment =
245
+ match export_binding with
246
+ | false -> " Check imported TypeScript value conforms to ReScript type"
247
+ | true -> " "
248
+ in
249
+ EmitType. emit_const_satisfies ~early: true ~emitters ~config
250
+ ~satisfies_type: rescript_type ~type_name_is_interface ~comment
251
+ value_name_type_checked expr
252
+ | None ->
253
+ imported_as_name ^ rest_of_path
254
+ |> EmitType. emit_export_const ~config
255
+ ~comment:
256
+ (" In case of type error, check the type of '" ^ value_name
257
+ ^ " ' in '"
258
+ ^ (file_name |> ModuleName. to_string)
259
+ ^ " .res'" ^ " and '"
260
+ ^ (import_path |> ImportPath. emit)
261
+ ^ " '." )
262
+ ~early: true ~emitters ~name: value_name_type_checked ~type_: type_for_emit
263
+ ~type_name_is_interface
236
264
in
237
265
let value_name_not_default =
238
266
match value_name = " default" with
239
267
| true -> Runtime. default
240
268
| false -> value_name
241
269
in
242
- let emitters =
243
- value_name_type_checked
244
- |> EmitType. emit_type_cast ~config ~type_ ~type_name_is_interface
245
- |> EmitType. emit_export_const
246
- ~comment:
247
- (" Export '" ^ value_name_not_default
248
- ^ " ' early to allow circular import from the '.bs.js' file." )
249
- ~config ~early: true ~emitters ~name: value_name_not_default
250
- ~type_: unknown ~type_name_is_interface
251
- in
252
- let emitters =
253
- match value_name = " default" with
254
- | true -> EmitType. emit_export_default ~emitters value_name_not_default
255
- | false -> emitters
270
+ let env, emitters =
271
+ match export_binding with
272
+ | false -> (env, emitters)
273
+ | true ->
274
+ let emitters =
275
+ match satisfies_rescript_type_opt with
276
+ | Some _ ->
277
+ (* For satisfies, we can assign the typed binding directly without casts. *)
278
+ EmitType. emit_export_const_assign_value ~early: true ~emitters ~config
279
+ ~name: value_name_not_default ~type_: type_for_emit
280
+ ~type_name_is_interface value_name_type_checked
281
+ ~comment:
282
+ (" Export '" ^ value_name_not_default
283
+ ^ " ' early to allow circular import from the '.bs.js' file." )
284
+ | None ->
285
+ value_name_type_checked
286
+ |> EmitType. emit_type_cast ~config ~type_: type_for_emit
287
+ ~type_name_is_interface
288
+ |> EmitType. emit_export_const
289
+ ~comment:
290
+ (" Export '" ^ value_name_not_default
291
+ ^ " ' early to allow circular import from the '.bs.js' file." )
292
+ ~config ~early: true ~emitters ~name: value_name_not_default
293
+ ~type_: unknown ~type_name_is_interface
294
+ in
295
+ let emitters =
296
+ match value_name = " default" with
297
+ | true -> EmitType. emit_export_default ~emitters value_name_not_default
298
+ | false -> emitters
299
+ in
300
+ ({env with imported_value_or_component = true }, emitters)
256
301
in
257
- ({ env with imported_value_or_component = true } , emitters)
302
+ (env, emitters)
258
303
| ExportValue
259
304
{doc_string; module_access_path; original_name; resolved_name; type_} ->
260
305
let resolved_name_str = ResolvedName. to_string resolved_name in
0 commit comments