Modelling a Javascript object in Purescript

Viewed 283

I'm trying to model in Purescript the SetOptions data type from Firestore.

Up to now I have the following

foreign import data FieldPath :: Type

foreign import buildFieldPath :: Array String -> FieldPath

foreign import fieldNames :: FieldPath -> Array String

type MergeFields = Array (String \/ FieldPath)

data SetOptions
  = MergeOption Merge
  | MergeFieldsOption MergeFields

Note that SetOptions is a sum type since the merge and mergeFields are mutually exclusive (even if this is not documented).

Now I need to convert SetOptions into a Javascript object, so that I can pass it to some function from the Javascript firebase library.

It should be something of the form

{
  "mergeFields": [
    "foo",
    new FieldPath("bar", "baz")
  ]
}

My issue is the type of this.

I can't use Object since the contained data are not homogeneous (merge refers to booleans, mergeFields refers to arrays).

I can't use Json because I need to have FieldPath objects in the result.

The only solution I found up to now is returning some Json and then on the javascript side parse it and add the FieldPath objects where needed, but it looks dirty and brittle.

1 Answers

I would probably skip coproduct SetOption representation on the PS side and just provide these two "dirty" constructors:

foreign import data SetOption :: Type

merge :: Boolean -> SetOption
merge m = unsafeCoerce { merge: m }

mergeFields :: MergeFields -> SetOption
mergeFields mf = unsafeCoerce { mergeFields: mf }

I would probably do the same for MergeFields coproduct.

We are doing something similar in our community project - material ui bindings: purescript-react-basic-mui. Additionally we are grouping these related constructors into records to achieve "cheap namespacing" because we are generating all these bindings from typescript declarations, but this is not really important in this context. Please take a look at some definitions in this example module:

https://github.com/purescript-react-basic-mui/purescript-react-basic-mui/blob/codegen-read-dts/src/MUI/Core/Badge.purs#L20

EDIT: I think that this latest discourse thread can be a good additional inspiration for you @macrosh.

Related