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.
11
+
12
+
Next.js has a `useNavigation` hook that returns an unknown type,
13
+
and it's up to the developer to add in a type annotation to define the type of 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.
9
19
<CodeTablabels={["ReScript", "JS Output"]}>
10
20
```res example
11
21
module Next = {
12
-
// define a module type to use a parameter for out module function
13
-
module type Params = {
14
-
type t
15
-
}
16
-
17
22
// define our module function
18
-
module MakeNavigation = (Params: Params) => {
23
+
module MakeNavigation = (Params: { type t }) => {
19
24
@module("next/navigation")
20
25
external useNavigation: unit => Params.t = "useNavigation"
21
26
/* You can use values from the function parameter, such as Params.t */
@@ -88,5 +93,56 @@ export {
88
93
}
89
94
/* next/navigation Not a pure module */
90
95
96
+
```
97
+
</ CodeTab>
98
+
99
+
This becomes incredibly useful when you need to have types that are unique to a project but shared across multiple components.
100
+
Let's say you want to create a library with a `useEnv` hook to load in environment variables found in `import.meta.env`.
101
+
```res
102
+
@val external env: 'a = "import.meta.env"
103
+
104
+
let useEnv = () => {
105
+
env
106
+
}
107
+
```
108
+
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 hook.
109
+
```res
110
+
type t = {"LOG_LEVEL": string}
111
+
112
+
let values: t = useEnv()
113
+
```
114
+
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.
115
+
116
+
We can instead create a module function that can return a module that has contains a `useEnv` hook that has a typed response.
117
+
```res
118
+
module MakeEnv = (
119
+
E: {
120
+
type t
121
+
},
122
+
) => {
123
+
@val external env: E.t = "import.meta.env"
124
+
125
+
let useEnv = () => {
126
+
env
127
+
}
128
+
}
129
+
```
130
+
And now consumers of our library can define the types and create a custom version of the hook just for their application.
131
+
Notice that in the JavaScript output that the `import.meta.env` is used directly and doesn't require any function calls or runtime overhead.
0 commit comments