You can make your own versions of Obj.magic that have more restrictions when necessary:
type t
external coerce: 'a => t = "%identity"
Or only coerce after verification:
let rawCode: unknown = Obj.magic(e)["code"]
if Js.typeof(rawCode) === "number" {
let code: int = rawCode->Obj.magic
// do something
}
Or make accessors instead of using the js[field] syntax:
@get external code: 'a => option<int> = "code"
// when null is possible
@get @return(nullable) external code: 'a => option<int> = "code"
// with some verification
let code = t => t->code-Option.flatMap(code => Number.isInteger(code) ? Some(code) : None)
// or when ReScript isn't simple enough
let code: 'a => int = %raw(`t => t?.some?.nested?.property?.code ?? 0`)
Lastly, use a JSON decoding library to convert unknown values into ReScript records.