The purpose of this proposal is to outline a design for handling bindings in ReScript that is safe and easy to use. Bindings are an important aspect of ReScript, as they allow developers to use external JavaScript code and libraries in their ReScript projects.
Currently, ReScript provides several ways to handle bindings, including using the @module
annotation and the %raw
syntax. While these methods work well, they can be complex and error-prone, especially when dealing with large and complex external libraries.
In this document, we will explore two alternatives for handling bindings in ReScript without using import
. The first approach combines the @module
and %raw
annotations, while the second approach utilizes a single @module
annotation for more concise and straightforward code.
To handle bindings in ReScript without using import
, one approach is to use a combination of the @module
and %raw
annotations. The @module
annotation allows you to import an external module and bind it to a value, while the %raw
annotation lets you embed raw JavaScript code in your ReScript file.
Here's an example of how you could use both @module
and %raw
to achieve a similar result:
type path = {
dirname: string => string,
}
// Using @module to import 'path' and binding it to a value
@module("path") external path: path = "default"
// Binding to the external JavaScript API using %raw
let getName: window => string = %raw(`x => x.name`)
This code imports the path
module using the @module
annotation and binds it to the path
value. Then, it uses %raw
to bind to the name
property of the window
object in JavaScript.
A more concise and straightforward approach is to use a single @module
annotation to import an external module and bind it to a value.
Here's an example using the Garmin API with a single @module
annotation:
// Define a type for the Garmin API
type garminApi = {
getHeartRateData: () => array<int>,
getElevationData: () => array<int>,
}
// Import the Garmin API using @module and bind it to a value
@module("garmin-api") external garminApi: garminApi = "default"
// Access the getHeartRateData and getElevationData functions from the Garmin API
let heartRateData = garminApi.getHeartRateData()
let elevationData = garminApi.getElevationData()
In this example, we first define the garminApi
type, which includes the getHeartRateData
and getElevationData
functions. Then, we use a single @module
annotation to import the Garmin API and bind it to a value named garminApi
.
Finally, we access the getHeartRateData
and getElevationData
functions directly from the garminApi
value.
Now take all the examples in rescript-lang/rescript-lang.org#572 (comment) and write them according to this proposal: