You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: pages/docs/manual/latest/record.mdx
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -151,6 +151,12 @@ baby.age = baby.age + 1 | 0;
151
151
152
152
</CodeTab>
153
153
154
+
Fields not marked with `mutable` in the type declaration cannot be mutated.
155
+
156
+
## JavaScript Output
157
+
158
+
ReScript records compile to straightforward JavaScript objects; see the various JS output tabs above.
159
+
154
160
## Tips & Tricks
155
161
156
162
**Record Types Are Found By Field Name**. With records, you **cannot** say "I'd like this function to take any record type, as long as they have the field `age`". The following **won't work as intended**:
If a variant payload has multiple fields, you can use a record-like syntax to label them for better readability:
107
107
108
108
<CodeTablabels={["ReScript", "JS Output"]}>
109
109
110
110
```res example
111
-
type idType = {name: string, password: string}
112
-
113
111
type user =
114
112
| Number(int)
115
-
| Id(idType)
113
+
| Id({name: string, password: string})
114
+
115
+
let me = Id({name: "Joe", password: "123"})
116
116
```
117
117
```js
118
-
// Empty output
118
+
var me = {
119
+
TAG:/* Id */1,
120
+
name:"Joe",
121
+
password:"123"
122
+
};
119
123
```
120
124
121
125
</CodeTab>
122
126
123
-
If the record type is used only in the variant definition, you may put it in line:
127
+
This is technically called an "inline record", and only allowed within a variant constructor. You cannot inline a record type declaration anywhere else in ReScript.
128
+
129
+
Of course, you can just put a regular record type in a variant too:
124
130
125
131
<CodeTablabels={["ReScript", "JS Output"]}>
126
132
127
133
```res example
134
+
type u = {name: string, password: string}
128
135
type user =
129
136
| Number(int)
130
-
| Id({name: string, password: string})
137
+
| Id(u)
138
+
139
+
let me = Id({name: "Joe", password: "123"})
131
140
```
132
141
```js
133
-
// Empty output
142
+
var me = {
143
+
TAG:/* Id */1,
144
+
_0: {
145
+
name:"Joe",
146
+
password:"123"
147
+
}
148
+
};
134
149
```
135
150
136
151
</CodeTab>
137
152
153
+
The output is slightly uglier and less performant than the former.
154
+
138
155
### Pattern Matching On Variant
139
156
140
157
See the [Pattern Matching/Destructuring](pattern-matching-destructuring.md) section later.
141
158
159
+
## JavaScript Output
160
+
161
+
A variant value compiles to 3 possible JavaScript outputs depending on its type declaration:
162
+
163
+
- If the variant value is a constructor with no payload, it compiles to a number.
164
+
- If it's a constructor with a payload, it compiles to an object with the field `TAG` and the field `_0` for the first payload, `_1` for the second payload, etc.
165
+
- An exception to the above is a variant whose type declaration contains only a single constructor with payload. In that case, the constructor compiles to an object without the `TAG` field.
166
+
- Labeled variant payloads (the inline record trick earlier) compile to an object with the label names instead of `_0`, `_1`, etc. The object might or might not have the `TAG` field as per previous rule.
167
+
168
+
Check the output in these examples:
169
+
170
+
<CodeTablabels={["ReScript", "JS Output"]}>
171
+
172
+
```res example
173
+
type greeting = Hello | Goodbye
174
+
let g1 = Hello
175
+
let g2 = Goodbye
176
+
177
+
type outcome = Good | Error(string)
178
+
let o1 = Good
179
+
let o2 = Error("oops!")
180
+
181
+
type family = Child | Mom(int, string) | Dad (int)
182
+
let f1 = Child
183
+
let f2 = Mom(30, "Jane")
184
+
let f3 = Dad(32)
185
+
186
+
type person = Teacher | Student({gpa: float})
187
+
let p1 = Teacher
188
+
let p2 = Student({gpa: 99.5})
189
+
190
+
type s = {score: float}
191
+
type adventurer = Warrior(s) | Wizard(string)
192
+
let a1 = Warrior({score: 10.5})
193
+
let a2 = Wizard("Joe")
194
+
```
195
+
```js
196
+
var g1 =/* Hello */0;
197
+
var g2 =/* Goodbye */1;
198
+
199
+
var o1 =/* Good */0;
200
+
var o2 =/* Error */{
201
+
_0:"oops!"
202
+
};
203
+
204
+
var f1 =/* Child */0;
205
+
var f2 = {
206
+
TAG:/* Mom */0,
207
+
_0:30,
208
+
_1:"Jane"
209
+
};
210
+
var f3 = {
211
+
TAG:/* Dad */1,
212
+
_0:32
213
+
};
214
+
215
+
var p1 =/* Teacher */0;
216
+
var p2 =/* Student */{
217
+
gpa:99.5
218
+
};
219
+
220
+
var a1 = {
221
+
TAG:/* Warrior */0,
222
+
_0: {
223
+
score:10.5
224
+
}
225
+
};
226
+
var a2 = {
227
+
TAG:/* Wizard */1,
228
+
_0:"Joe"
229
+
};
230
+
```
231
+
232
+
</CodeTab>
233
+
142
234
## Tips & Tricks
143
235
144
236
**Be careful** not to confuse a constructor carrying 2 arguments with a constructor carrying a single tuple argument:
@@ -155,10 +247,10 @@ type account2 =
155
247
// Empty output
156
248
```
157
249
158
-
### Variants Must Have Constructors
159
-
160
250
</CodeTab>
161
251
252
+
### Variants Must Have Constructors
253
+
162
254
If you come from an untyped language, you might be tempted to try `type myType = int | string`. This isn't possible in ReScript; you'd have to give each branch a constructor: `type myType = Int(int) | String(string)`. The former looks nice, but causes lots of trouble down the line.
163
255
164
256
### Interop with JavaScript
@@ -200,7 +292,7 @@ betterDraw({
200
292
201
293
</CodeTab>
202
294
203
-
You could definitely do that, but there are better ways! For example, define two `external`s that both compile to the same JS call:
295
+
**Try not to do that**, as this generates extra noisy output. Alternatively, define two `external`s that both compile to the same JS call:
0 commit comments