拆箱
考虑一个单 payload 变体和一个单字段记录:
如果你检查 JavaScript 的输出,你将看到 studentName
和 hi
JS 对象,正如预期的那样(详见变体的 JS 输出和记录的 JS 输出)。
对于需求性能和某些与 JavaScript 互操作情况,ReScript 提供了一种从输出中解包(也就是拆箱)JS 对象包装的方法,它用于单字段记录和单 payload 单构造器变体。用属性 @unboxed
来标注它们的类型声明:
检查新的输出!嗯,很干净。
用法
为什么你会想要只有单个 payload 的变体或记录?为什么不直接...直接传递 payload ?这是变体的一种使用场景。
假设你有一个具有局部/全局坐标系的游戏:
type coordinates = {x: float, y: float}
let renderDot = (coordinates) => {
Js.log3("Pretend to draw at:", coordinates.x, coordinates.y)
}
let toWorldCoordinates = (localCoordinates) => {
{
x: localCoordinates.x +. 10.,
y: localCoordinates.x +. 20.,
}
}
let playerLocalCoordinates = {x: 20.5, y: 30.5}
renderDot(playerLocalCoordinates)
哦,出错了!renderDot
应该使用全局坐标系,而不是局部的... 让我们防止传递错误的坐标系:
type coordinates = {x: float, y: float}
@unboxed type localCoordinates = Local(coordinates)
@unboxed type worldCoordinates = World(coordinates)
let renderDot = (World(coordinates)) => {
Js.log3("Pretend to draw at:", coordinates.x, coordinates.y)
}
let toWorldCoordinates = (Local(coordinates)) => {
World({
x: coordinates.x +. 10.,
y: coordinates.x +. 20.,
})
}
let playerLocalCoordinates = Local({x: 20.5, y: 30.5})
// This now errors!
// renderDot(playerLocalCoordinates)
// We're forced to do this instead:
renderDot(playerLocalCoordinates->toWorldCoordinates)
现在 renderDot
只接受 worldCoordinates
。通过使用不同的变体类型 + 参数解构这个完美结合,我们在不影响性能的情况下获得了更好的安全性:unboxed
属性编译为干净的、无变体包装的 JS 代码!检查一下输出。
至于单字段的记录,它们的使用情况有点太前卫了。我们不会在这里提到它们。