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
Module functions can be used to create modules based on types, values, or functions from other modules.
10
-
This is a powerful tool that can be used to created abstractions and reusable code that might not be possible with functions, or might have a runtime cost if done with functions.
10
+
This is a powerful tool that can be used to create abstractions and reusable code that might not be possible with functions, or might have a runtime cost if done with functions.
11
+
12
+
This is an advanced part of ReScript and you can generally get by with normal values and functions.
11
13
12
14
## Quick example
13
-
Next.js has a `useNavigation` hook that returns an unknown type,
14
-
and it's up to the developer to add in a type annotation to define the type of the parameters returned by the hook.
15
+
Next.js has a `useParams` hook that returns an unknown type,
16
+
and it's up to the developer in TypeScript to add a type annotation for the parameters returned by the hook.
Instead of having to add the type annotation every time you use the hook, you can create a module function that will return a typed response for the `useNavigation` hook.
21
+
In ReScript we can create a module function that will return a typed response for the `useParams` hook.
20
22
<CodeTablabels={["ReScript", "JS Output"]}>
21
23
```res example
22
24
module Next = {
23
25
// define our module function
24
-
module MakeNavigation = (Params: { type t }) => {
26
+
module MakeParams = (Params: { type t }) => {
25
27
@module("next/navigation")
26
-
external useNavigation: unit => Params.t = "useNavigation"
28
+
external useParams: unit => Params.t = "useParams"
27
29
/* You can use values from the function parameter, such as Params.t */
28
30
}
29
31
}
@@ -32,21 +34,21 @@ module Component: {
32
34
@react.component
33
35
let make: unit => Jsx.element
34
36
} = {
35
-
// Create a module that matches the module type expected by Next.MakeNavigation
36
-
module Params = {
37
+
// Create a module that matches the module type expected by Next.MakeParams
38
+
module P = {
37
39
type t = {
38
40
tag: string,
39
41
item: string,
40
42
}
41
43
}
42
44
43
-
// Create a new module using the Params module we created and the Next.MakeNavigation module function
44
-
module Navigation = Next.MakeNavigation(Params)
45
+
// Create a new module using the Params module we created and the Next.MakeParams module function
46
+
module Params = Next.MakeParams(P)
45
47
46
48
@react.component
47
49
let make = () => {
48
50
// Use the functions, values, or types created by the module function
49
-
let params = Navigation.useNavigation()
51
+
let params = Params.useParams()
50
52
<div>
51
53
<p>
52
54
{React.string("Tag: " ++ params.tag /* params is fully typed! */)}
@@ -62,16 +64,16 @@ module Component: {
62
64
import*as $$Navigationfrom"next/navigation";
63
65
import*asJsxRuntimefrom"react/jsx-runtime";
64
66
65
-
functionMakeNavigation(Params) {
67
+
functionMakeParams(Params) {
66
68
return {};
67
69
}
68
70
69
71
var Next = {
70
-
MakeNavigation: MakeNavigation
72
+
MakeParams: MakeParams
71
73
};
72
74
73
75
functionPlayground$Component(props) {
74
-
var params =$$Navigation.useNavigation();
76
+
var params =$$Navigation.useParams();
75
77
returnJsxRuntime.jsxs("div", {
76
78
children: [
77
79
JsxRuntime.jsx("p", {
@@ -107,15 +109,15 @@ let getEnv = () => {
107
109
env
108
110
}
109
111
```
110
-
It's not possible to define types for this that will work for every project, so we just set it as 'a and the consumer of our library can define the return type when they use the function.
112
+
It's not possible to define types for this that will work for every project, so we just set it as 'a and the consumer of our library can define the return type.
111
113
```res
112
114
type t = {"LOG_LEVEL": string}
113
115
114
116
let values: t = getEnv()
115
117
```
116
118
This isn't great and it doesn't take advantage of ReScript's type system and ability to use types without type definitions, and it can't be easily shared across our application.
117
119
118
-
We can instead create a module function that can return a module that has contains a `getEnv`hook that has a typed response.
120
+
We can instead create a module function that can return a module that has contains a `getEnv`function that has a typed response.
119
121
```res
120
122
module MakeEnv = (
121
123
E: {
@@ -129,7 +131,7 @@ module MakeEnv = (
129
131
}
130
132
}
131
133
```
132
-
And now consumers of our library can define the types and create a custom version of the hook just for their application.
134
+
And now consumers of our library can define the types and create a custom version of the hook for their application.
133
135
Notice that in the JavaScript output that the `import.meta.env` is used directly and doesn't require any function calls or runtime overhead.
134
136
135
137
<CodeTablabels={["ReScript", "JS Output"]}>
@@ -249,7 +251,7 @@ function Person$1(props) {
249
251
250
252
## Dependency injection
251
253
Module functions can be used for dependency injection.
252
-
Here's an example of injecting in a some config values into a set of functions to access a database.
254
+
Here's an example of injecting in some config values into a set of functions to access a database.
0 commit comments