/
OhYes.purs
143 lines (121 loc) · 4.08 KB
/
OhYes.purs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
module OhYes where
import Prelude
import Data.Foldable (intercalate)
import Data.Function.Uncurried (Fn2)
import Data.List (List, (:))
import Data.Monoid (mempty)
import Data.Nullable (Nullable)
import Data.Variant (Variant)
import Type.Prelude (class IsSymbol, SProxy(..), reflectSymbol)
import Type.Proxy (Proxy(..))
import Type.Row (class RowToList, Cons, Nil, RLProxy(..), kind RowList)
-- | identity function for applying the HasTSRep constraint
toTS :: forall a. HasTSRep a => a -> a
toTS = id
-- | Generate Typescript type signatures for a given type, supplying a name to use as the type name
generateTS :: forall a
. HasTSRep a
=> String -> Proxy a -> String
generateTS name _ = "export type " <> name <> " = " <> ty
where
p = Proxy :: Proxy a
ty = toTSRep p
-- | Our main type class for types that can be represented in Typescript types without conversion. You may want to using newtype instance deriving for this class for your newtypes, but any other types should be tested for correctness.
class HasTSRep a where
toTSRep :: Proxy a -> String
instance numberHasTSRep :: HasTSRep Number where
toTSRep _ = "number"
instance stringHasTSRep :: HasTSRep String where
toTSRep _ = "string"
instance booleanHasTSRep :: HasTSRep Boolean where
toTSRep _ = "boolean"
instance nullableHasTSRep ::
( HasTSRep a
) => HasTSRep (Nullable a) where
toTSRep _ = ty <> " | null"
where
p = Proxy :: Proxy a
ty = toTSRep p
instance arrayHasTSRep ::
( HasTSRep a
) => HasTSRep (Array a) where
toTSRep _ = toTSRep p <> "[]"
where
p = Proxy :: Proxy a
instance functionHasTSRep ::
( HasTSRep a
, HasTSRep b
) => HasTSRep (Function a b) where
toTSRep _ = "(a: " <> a <> ") => " <> b
where
a = toTSRep (Proxy :: Proxy a)
b = toTSRep (Proxy :: Proxy b)
instance fn2HasTSRep ::
( HasTSRep a
, HasTSRep b
, HasTSRep c
) => HasTSRep (Fn2 a b c) where
toTSRep _ =
"(a: " <> a <>
", b: " <> b <>
") => " <> c
where
a = toTSRep (Proxy :: Proxy a)
b = toTSRep (Proxy :: Proxy b)
c = toTSRep (Proxy :: Proxy c)
instance recordHasTSRep ::
( RowToList row rl
, HasTSRepFields rl
) => HasTSRep (Record row) where
toTSRep _ = "{" <> fields <> "}"
where
rlp = RLProxy :: RLProxy rl
fields = intercalate "," $ toTSRepFields rlp
class HasTSRepFields (rl :: RowList) where
toTSRepFields :: RLProxy rl -> List String
instance consHasTSRepFields ::
( HasTSRepFields tail
, IsSymbol name
, HasTSRep ty
) => HasTSRepFields (Cons name ty tail) where
toTSRepFields _ = head : tail
where
namep = SProxy :: SProxy name
key = reflectSymbol namep
typ = Proxy :: Proxy ty
val = toTSRep typ
head = key <> ":" <> val
tailp = RLProxy :: RLProxy tail
tail = toTSRepFields tailp
instance nilHasTSRepFields :: HasTSRepFields Nil where
toTSRepFields _ = mempty
-- | a Variant is represented by VariantRep, which is a newtype record of
-- | `newtype VariantRep a = VariantRep { type ∷ String , value ∷ a }`
-- | as seen here:
-- | https://github.com/natefaubion/purescript-variant/blob/aef507e2972d294ecd735575371eccbc61ac1ac4/src/Data/Variant/Internal.purs#L31
instance fakeSumRecordHasTSRep ::
( RowToList row rl
, FakeSumRecordMembers rl
) => HasTSRep (Variant row) where
toTSRep _ = intercalate "|" members
where
rlp = RLProxy :: RLProxy rl
members = toFakeSumRecordMembers rlp
class FakeSumRecordMembers (rl :: RowList) where
toFakeSumRecordMembers :: RLProxy rl -> List String
instance consFakeSumRecordMembers ::
( FakeSumRecordMembers tail
, IsSymbol name
, HasTSRep ty
) => FakeSumRecordMembers (Cons name ty tail) where
toFakeSumRecordMembers _ = head : tail
where
namep = SProxy :: SProxy name
key = reflectSymbol namep
typ = Proxy :: Proxy ty
val = toTSRep typ
head = "{type:\"" <> key <> "\", value:" <> val <> "}"
tailp = RLProxy :: RLProxy tail
tail = toFakeSumRecordMembers tailp
instance nilFakeSumRecordMembers :: FakeSumRecordMembers Nil where
toFakeSumRecordMembers _ = mempty