Help fixing this code

    let options = Js.Dict.fromList(list{
        ("hostname", hostname),
        ("port", port),
        ("path|", path),
        ("method", "POST"), 
        ("heders", Js.Dict.fromList(list{ ( "Content-Length", "") }))
        });

any one have advice on fixing this code? Most entries are (string, string), but the last entry is a (string, Js.Dict.t)

1 Like

I’m looking for a “any JS object” type, but not finding it.

A dict is specifically a string -> 'a mapping and the value can’t change.

For JS interop If you don’t plan on typing your options object, you can use an Object | ReScript Language Manual (rescript-lang.org)

exernal request: {..} => t = "request"

request({
  "hostname": hostname,
  "method": "post",
  "headers": {
    "Content-Length": ""
  }
})

Though for something like request options, I’d typically define the type in the binding and then you can set just the headers to a Dict

type method = [#GET | #POST]

type options = {
  hostname?: string,
  port?: int,
  path?: string,
  method: method,
  headers?: Dict.t<string>
}

let options = {
  hostname,
  port,
  path,
  method: #POST,
  headers: Dict.fromArray([
    ("Content-Length": "")
  ])
}
2 Likes

Does this object have a type? I tried things like Js.t, Js.obj, Js.Obj.t, …

For functions you can use {..} in the parameter

let thing = (x: {..}) => ()

For types I like using Js.Json.t since I feel it represents it the best. Then you can use Obj.magic() to cheat the type system

type postRequest = {
  url: string,
  data?: Js.Json.t
}

let request = {
  url: "/",
  data: Obj.magic({"key": "field"})
}

Though this is for data you truly don’t care about the shape for, each time you rely on this you reduce the safety of your codebase

1 Like

Your example is a Js.t<'a> where 'a is the structure of your object. See:

let x = {
  "hostname": "hostname",
  "method": "post",
  "headers": {
    "Content-Length": "",
  },
}

let y: Js.t<{
  "hostname": string,
  "method": string,
  "headers": {"Content-Length": string},
}> = x

let z: {
  "hostname": string,
  "method": string,
  "headers": {"Content-Length": string},
} = x

Try in the playground.

Note that {..} is an “open object notation” and allows just about any object structure as long as it’s a Js.t. This is very unsafe to use and should be handled with care.

Regarding Obj.magic: yes, this function exists… but you are actively puting holes into the type system when you use it.
If at all - you should use external identity functions:

external: someType => otherTypeWithSameRuntimeRepresentation = "%identity"

Using this is also puting holes in your types, but at least you are reducing the surface area, since it’s specific for two types.

Best to refrain from both aproaches, if possible!

1 Like