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/attribute.mdx
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ Like many other languages, ReScript allows annotating a piece of code to express
11
11
<CodeTablabels={["ReScript", "JS Output"]}>
12
12
13
13
```res
14
-
@bs.inline
14
+
@inline
15
15
let mode = "dev"
16
16
17
17
let mode2 = mode
@@ -22,7 +22,7 @@ var mode2 = "dev";
22
22
23
23
</CodeTab>
24
24
25
-
The `@bs.inline` annotation tells `mode`'s value to be inlined into its usage sites (see output). We call such annotation "attribute" (or "decorator" in JavaScript).
25
+
The `@inline` annotation tells `mode`'s value to be inlined into its usage sites (see output). We call such annotation "attribute" (or "decorator" in JavaScript).
26
26
27
27
An attribute starts with `@` and goes before the item it annotates. In the above example, it's hooked onto the let binding.
28
28
@@ -39,11 +39,11 @@ You can put an attribute almost anywhere. You can even add extra data to them by
@@ -101,20 +101,20 @@ var el = document.getElementById("myId");
101
101
102
102
</CodeTab>
103
103
104
-
In a `bs.send`, the object is always the first argument. Actual arguments of the method follow (this is a bit what modern OOP objects are really).
104
+
In a `send`, the object is always the first argument. Actual arguments of the method follow (this is a bit what modern OOP objects are really).
105
105
106
106
### Chaining
107
107
108
108
Ever used `foo().bar().baz()` chaining ("fluent api") in JS OOP? We can model that in ReScript too, through the [pipe operator](pipe.md).
109
109
110
110
## Variadic Function Arguments
111
111
112
-
You might have JS functions that take an arbitrary amount of arguments. ReScript supports modeling those, under the condition that the arbitrary arguments part is homogenous (aka of the same type). If so, add `bs.variadic` to your `external`.
112
+
You might have JS functions that take an arbitrary amount of arguments. ReScript supports modeling those, under the condition that the arbitrary arguments part is homogenous (aka of the same type). If so, add `variadic` to your `external`.
113
113
114
114
<CodeTablabels={["ReScript", "JS Output"]}>
115
115
116
116
```res example
117
-
@bs.module("path") @bs.variadic
117
+
@module("path") @variadic
118
118
external join: array<string> => string = "join"
119
119
120
120
let v = join(["a", "b"])
@@ -126,7 +126,7 @@ var v = Path.join("a", "b");
126
126
127
127
</CodeTab>
128
128
129
-
`bs.module` will be explained in [Import from/Export to JS](import-from-export-to-js.md).
129
+
`module` will be explained in [Import from/Export to JS](import-from-export-to-js.md).
130
130
131
131
## Modeling Polymorphic Function
132
132
@@ -139,9 +139,9 @@ If you can exhaustively enumerate the many forms an overloaded JS function can t
139
139
<CodeTablabels={["ReScript", "JS Output"]}>
140
140
141
141
```res example
142
-
@bs.module("MyGame") external drawCat: unit => unit = "draw"
143
-
@bs.module("MyGame") external drawDog: (~giveName: string) => unit = "draw"
144
-
@bs.module("MyGame") external draw: (string, ~useRandomAnimal: bool) => unit = "draw"
142
+
@module("MyGame") external drawCat: unit => unit = "draw"
143
+
@module("MyGame") external drawDog: (~giveName: string) => unit = "draw"
144
+
@module("MyGame") external draw: (string, ~useRandomAnimal: bool) => unit = "draw"
145
145
```
146
146
```js
147
147
// Empty output
@@ -151,7 +151,7 @@ If you can exhaustively enumerate the many forms an overloaded JS function can t
151
151
152
152
Note how all three externals bind to the same JS function, `draw`.
153
153
154
-
### Trick 2: Polymorphic Variant + `bs.unwrap`
154
+
### Trick 2: Polymorphic Variant + `unwrap`
155
155
156
156
If you have the irresistible urge of saying "if only this JS function argument was a variant instead of informally being either `string` or `int`", then good news: we do provide such `external` features through annotating a parameter as a polymorphic variant! Assuming you have the following JS function you'd like to bind to:
157
157
@@ -172,10 +172,10 @@ Here, `padding` is really conceptually a variant. Let's model it as such.
172
172
<CodeTablabels={["ReScript", "JS Output"]}>
173
173
174
174
```res example
175
-
@bs.val
175
+
@val
176
176
external padLeft: (
177
177
string,
178
-
@bs.unwrap [
178
+
@unwrap [
179
179
| #Str(string)
180
180
| #Int(int)
181
181
])
@@ -190,21 +190,21 @@ padLeft("Hello World", "Message from ReScript: ");
190
190
191
191
</CodeTab>
192
192
193
-
Obviously, the JS side couldn't have an argument that's a polymorphic variant! But here, we're just piggy backing on poly variants' type checking and syntax. The secret is the `@bs.unwrap` annotation on the type. It strips the variant constructors and compile to just the payload's value. See the output.
193
+
Obviously, the JS side couldn't have an argument that's a polymorphic variant! But here, we're just piggy backing on poly variants' type checking and syntax. The secret is the `@unwrap` annotation on the type. It strips the variant constructors and compile to just the payload's value. See the output.
194
194
195
195
## Constrain Arguments Better
196
196
197
-
Consider the Node `fs.readFileSync`'s second argument. It can take a string, but really only a defined set: `"ascii"`, `"utf8"`, etc. You can still bind it as a string, but we can use poly variants + `bs.string` to ensure that our usage's more correct:
197
+
Consider the Node `fs.readFileSync`'s second argument. It can take a string, but really only a defined set: `"ascii"`, `"utf8"`, etc. You can still bind it as a string, but we can use poly variants + `string` to ensure that our usage's more correct:
- Attaching `@bs.string` to the whole poly variant type makes its constructor compile to a string of the same name.
221
-
- Attaching a `@bs.as("bla")` to a constructor lets you customize the final string.
220
+
- Attaching `@string` to the whole poly variant type makes its constructor compile to a string of the same name.
221
+
- Attaching a `@as("bla")` to a constructor lets you customize the final string.
222
222
223
223
And now, passing something like `"myOwnUnicode"` or other variant constructor names to `readFileSync` would correctly error.
224
224
225
-
Aside from string, you can also compile an argument to an int, using `bs.int` instead of `bs.string` in a similar way:
225
+
Aside from string, you can also compile an argument to an int, using `int` instead of `string` in a similar way:
226
226
227
227
<CodeTablabels={["ReScript", "JS Output"]}>
228
228
229
229
```res example
230
-
@bs.val
230
+
@val
231
231
external testIntType: (
232
-
@bs.int [
232
+
@int [
233
233
| #onClosed
234
-
| @bs.as(20) #onOpen
234
+
| @as(20) #onOpen
235
235
| #inBinary
236
236
])
237
237
=> int = "testIntType"
@@ -254,10 +254,10 @@ One last trick with polymorphic variants:
254
254
```res example
255
255
type readline
256
256
257
-
@bs.send
257
+
@send
258
258
external on: (
259
259
readline,
260
-
@bs.string [
260
+
@string [
261
261
| #close(unit => unit)
262
262
| #line(string => unit)
263
263
]
@@ -290,9 +290,9 @@ Sometimes it's convenient to bind to a function using an `external`, while passi
290
290
<CodeTablabels={["ReScript", "JS Output"]}>
291
291
292
292
```res example
293
-
@bs.val
293
+
@val
294
294
external processOnExit: (
295
-
@bs.as("exit") _,
295
+
@as("exit") _,
296
296
int => unit
297
297
) => unit = "process.on"
298
298
@@ -308,7 +308,7 @@ process.on("exit", function (exitCode) {
308
308
309
309
</CodeTab>
310
310
311
-
The `@bs.as("exit")` and the placeholder `_` argument together indicates that you want the first argument to compile to the string `"exit"`. You can also use any JSON literal with `bs.as`: `` @bs.as(json`true`) ``, `` @bs.as(json`{"name": "John"}`) ``, etc.
311
+
The `@as("exit")` and the placeholder `_` argument together indicates that you want the first argument to compile to the string `"exit"`. You can also use any JSON literal with `as`: `` @as(json`true`) ``, `` @as(json`{"name": "John"}`) ``, etc.
312
312
313
313
## Curry & Uncurry
314
314
@@ -338,7 +338,7 @@ Unfortunately, due to JS not having currying because of the aforementioned reaso
338
338
339
339
ReScript tries to do #1 as much as it can. Even when it bails and uses #2's currying mechanism, it's usually harmless.
340
340
341
-
**However**, if you encounter #3, heuristics are not good enough: you need a guaranteed way of fully applying a function, without intermediate currying steps. We provide such guarantee through the use of the `@bs`"uncurrying" annotation on a function declaration & call site.
341
+
**However**, if you encounter #3, heuristics are not good enough: you need a guaranteed way of fully applying a function, without intermediate currying steps. We provide such guarantee through the use of the ["uncurrying" syntax](./function#uncurried-function) on a function declaration & call site.
342
342
343
343
### Solution: Use Guaranteed Uncurrying
344
344
@@ -348,7 +348,7 @@ ReScript tries to do #1 as much as it can. Even when it bails and uses #2's curr
In general, `bs.uncurry` is recommended; the compiler will do lots of optimizations to resolve the currying to uncurrying at compile time. However, there are some cases the compiler can't optimize it. In these cases, it will be converted to a runtime check.
387
+
In general, `uncurry` is recommended; the compiler will do lots of optimizations to resolve the currying to uncurrying at compile time. However, there are some cases the compiler can't optimize it. In these cases, it will be converted to a runtime check.
388
388
389
389
## Modeling `this`-based Callbacks
390
390
@@ -396,16 +396,16 @@ x.onload = function(v) {
396
396
}
397
397
```
398
398
399
-
Here, `this` would point to `x` (actually, it depends on how `onload` is called, but we digress). It's not correct to declare `x.onload` of type `(. unit) -> unit`. Instead, we introduced a special attribute, `bs.this`, which allows us to type `x` as so:
399
+
Here, `this` would point to `x` (actually, it depends on how `onload` is called, but we digress). It's not correct to declare `x.onload` of type `(. unit) -> unit`. Instead, we introduced a special attribute, `this`, which allows us to type `x` as so:
`bs.this` has its first parameter is reserved for `this` and for arity of 0, there is no need for a redundant `unit` type.
419
+
`this` has its first parameter is reserved for `this` and for arity of 0, there is no need for a redundant `unit` type.
420
420
421
421
## Function Nullable Return Value Wrapping
422
422
423
-
For JS functions that return a value that can also be `undefined` or `null`, we provide `@bs.return(...)`. To automatically convert that value to an `option` type (recall that ReScript `option` type's `None` value only compiles to `undefined` and not `null`).
423
+
For JS functions that return a value that can also be `undefined` or `null`, we provide `@return(...)`. To automatically convert that value to an `option` type (recall that ReScript `option` type's `None` value only compiles to `undefined` and not `null`).
0 commit comments