Rescript中open语句无法将模块函数导入作用域问题咨询
问题根源
你遇到的异常表现完全是模块嵌套导致的,和Rescript的open语法本身逻辑无关:
Rescript 中每个.res文件本身就是一个顶层模块,模块名默认是文件名的大驼峰格式,你在FileReader.res中又额外定义了一层同名子模块module FileReader = { ... },相当于你现在的模块结构是两层嵌套:
- 顶层模块:
FileReader(对应整个FileReader.res文件) - 子模块:
FileReader.FileReader(你在文件内手动定义的模块)fileToDataUrl方法定义在子模块中,而不是直接定义在顶层文件模块下,才会出现你遇到的所有异常表现。
各报错原因解释
- 去掉
open语句时用FileReader.fileToDataUrl报错:你访问的是顶层FileReader模块下的方法,顶层模块下只有子模块FileReader,没有直接定义fileToDataUrl,自然找不到。 - 保留
open FileReader直接用fileToDataUrl报错:open FileReader是把顶层FileReader模块的导出内容注入当前作用域,顶层模块只导出了子模块FileReader,没有导出fileToDataUrl,所以也找不到。 - 同时保留
open和FileReader.前缀能编译但有警告:open FileReader之后,当前作用域的FileReader标识符就指向了顶层模块导出的子模块FileReader.FileReader,这时候FileReader.fileToDataUrl实际是访问子模块的方法,逻辑是通的;但open操作把顶层的FileReader模块标识符遮蔽成了子模块,所以会触发44号警告。
解决方法
方案1(推荐):调整FileReader.res的结构
去掉文件内多余的嵌套模块定义,直接把所有内容写在文件顶层:
// FileReader.res 调整后内容 type fileReader type file = {"name": string, "lastModified": int, "size": int, "type__": string} @new external createFileReader: unit => fileReader = "FileReader" @bs.send external readAsDataURL: (fileReader, file) => unit = "readAsDataURL" let onload: (fileReader, string => unit) => unit = %raw(` function (reader, cb) { reader.onload = function (e) { cb(e.target.result); } } `) let fileToDataUrl: (file, string => unit) => unit = (file, continue) => { let reader = createFileReader() onload(reader, continue) readAsDataURL(reader, file) }
调整后就符合你的预期:要么添加open FileReader之后直接调用fileToDataUrl,要么不写open直接用FileReader.fileToDataUrl,两种方式二选一即可,不会报错也不会有警告。
方案2:不调整现有模块结构,适配调用方式
如果你要保留现在的两层嵌套结构,有两种正确用法:
- 不写
open,调用时写全路径:FileReader.FileReader.fileToDataUrl(setDataUrlState) - 直接open内层子模块:
open FileReader.FileReader,之后直接调用fileToDataUrl(setDataUrlState)即可,不会有警告。
内容的提问来源于stack exchange,提问作者akaphenom
相关产品推荐
相关产品推荐

