codedownio / aeson-typescript

Generate TypeScript definition files from your ADTs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Extend Map instance to handle `ToJSONKeyValue` keys

Ptival opened this issue · comments

This code:

instance (TypeScript a, TypeScript b) => TypeScript (Map a b) where
getTypeScriptType _ = "{[k in " ++ getTypeScriptKeyType (Proxy :: Proxy a) ++ "]?: " ++ getTypeScriptType (Proxy :: Proxy b) ++ "}"
getParentTypes _ = [TSType (Proxy :: Proxy a), TSType (Proxy :: Proxy b)]

seems to assume aeson generates maps for Data.Map.

This does not appear to be the case. Since JavaScript maps must be keyed by strings, aeson instead generates key-value pairs, see:

https://github.com/haskell/aeson/blob/65fca856304c0b323d538cc783493d8d7a145114/src/Data/Aeson/Types/ToJSON.hs#L1684

and the discussions at:

haskell/aeson#259
haskell/aeson#79

It seems aeson-typescript should instead generate key-value pairs.

It certainly encodes to a JSON object for every case I'm aware of. Those are some pretty old issues also. Do you have an example of this?

Oh, I guess this can happen when you use a ToJSONKeyValue function, see https://hackage.haskell.org/package/aeson-2.0.3.0/docs/Data-Aeson-Types.html#t:ToJSONKey

Ah indeed, in our example we have a:

newtype Name (sym :: Symbol) = Name { name :: Text }
  deriving (Eq, Ord, Show, Generic, NFData)

that has a ToJSONKey instance and is used as the key of a Map Name ...!

Yep, sounds like we need to modify the instance to handle this case. Wouldn't you rather just use ToJSONKeyText? IIRC you can even auto derive it from a newtype like this.

Sorry I mistyped, just a ToJSONKey* instance. I don't think we call either of toJSONKeyValue or toJSONKeyText explicitly, but I'm not certain as I did not write those instances.