Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/Data/Aeson/TypeScript/TH.hs
Original file line number Diff line number Diff line change
Expand Up @@ -308,10 +308,19 @@ handleConstructor (ExtraTypeScriptOptions {..}) options (DatatypeInfo {..}) gene
interfaceName = "I" <> (lastNameComponent' $ constructorName ci)

tupleEncoding = do
let typ = contentsTupleTypeSubstituted genericVariables ci
stringExp <- lift $ case typ of
(AppT (ConT name) t) | name == ''Maybe -> [|$(getTypeAsStringExp t) <> " | null"|]
_ -> getTypeAsStringExp typ
let fields = constructorFields ci
stringExp <- lift $ case fields of
[] -> [|"void[]"|]
[x] -> case mapType genericVariables x of
(AppT (ConT name) t) | name == ''Maybe -> [|$(getTypeAsStringExp t) <> " | null"|]
mappedType -> getTypeAsStringExp mappedType
xs -> do
-- Process each field individually to handle Maybe types
fieldStrings <- forM (fmap (mapType genericVariables) xs) $ \fieldType -> case fieldType of
(AppT (ConT name) t) | name == ''Maybe -> [|$(getTypeAsStringExp t) <> " | null"|]
_ -> getTypeAsStringExp fieldType
let fieldExps = map return fieldStrings
[|"[" <> $(foldr1 (\a b -> [|$a <> ", " <> $b|]) fieldExps) <> "]"|]

lift [|TSTypeAlternatives $(TH.stringE interfaceName)
$(genericVariablesListExpr True genericVariables)
Expand Down
31 changes: 31 additions & 0 deletions test/Basic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module Basic (tests) where
import Data.Aeson as A
import Data.Aeson.TypeScript.TH
import Data.Aeson.TypeScript.Types
import Data.List.NonEmpty (NonEmpty)
import Data.Proxy
import Data.String.Interpolate
import Prelude hiding (Double)
Expand All @@ -20,6 +21,24 @@ $(deriveTypeScript (A.defaultOptions { A.tagSingleConstructors = True
data Test1 = Test1 (Maybe Int)
deriveTypeScript A.defaultOptions ''Test1

data Test2 = Test2 String [Int] (Maybe String)
deriveTypeScript A.defaultOptions ''Test2

-- Test case for Maybe types in multi-field tuples
data PromptKey = PromptKey String deriving (Eq, Show)

$(deriveTypeScript A.defaultOptions ''PromptKey)

newtype ExtraInputPrompt = ExtraInputPrompt String deriving (Eq, Show)

$(deriveTypeScript A.defaultOptions ''ExtraInputPrompt)

data WidgetActionPayload
= InfoRequest String [PromptKey] (Maybe (NonEmpty ExtraInputPrompt))
deriving (Eq, Show)

$(deriveTypeScript A.defaultOptions ''WidgetActionPayload)

tests :: SpecWith ()
tests = describe "Basic tests" $ do
describe "tagSingleConstructors and constructorTagModifier" $ do
Expand All @@ -40,6 +59,18 @@ tests = describe "Basic tests" $ do
, TSTypeAlternatives "ITest1" [] ["number | null"] Nothing
])

it [i|Maybe in multi-field tuple includes null option|] $ do
(getTypeScriptDeclarations (Proxy :: Proxy Test2)) `shouldBe` ([
TSTypeAlternatives "Test2" [] ["ITest2"] Nothing
, TSTypeAlternatives "ITest2" [] ["[string, number[], string | null]"] Nothing
])

it [i|WidgetActionPayload tuple includes null for Maybe list|] $ do
(getTypeScriptDeclarations (Proxy :: Proxy WidgetActionPayload))
`shouldBe` ( [ TSTypeAlternatives "WidgetActionPayload" [] ["IInfoRequest"] Nothing,
TSTypeAlternatives "IInfoRequest" [] ["[string, PromptKey[], ExtraInputPrompt[] | null]"] Nothing
]
)

main :: IO ()
main = hspec tests