sanctuary-js / sanctuary-def

Run-time type system for JavaScript
MIT License
294 stars 23 forks source link

Module type should be added to default env #218

Closed mfidemraizer closed 4 years ago

mfidemraizer commented 6 years ago

When a module is imported using dynamic imports (i.e. import(...) / import :: String -> Promise Module), the returned value is Module which is like an object.

Since dynamic imports will be used more and more, I consider that sanctuary-def should include Module type as part of its default env.

davidchambers commented 6 years ago

Could you propose a predicate function, @mfidemraizer?

Avaq commented 6 years ago

Try this:

$ cd `mktemp -d`
$ echo 'export default 42' > export.mjs
$ echo 'import("./export.mjs").then(module => console.log(toString.call(module)))' > import.mjs
$ node --experimental-modules --no-warnings import.mjs
[object Module]

So the predicate function could be:

x => Object.prototype.toString.call(x) === '[object Module]'
davidchambers commented 6 years ago

Cool. Feel free to submit a pull request. :)

mfidemraizer commented 6 years ago

Yeah, in fact I resolved this in my own code just like @Avaq has proposed.

mfidemraizer commented 6 years ago

Oh and I tried to find another approach but it seems like toString is the unique approach to identify Module type: https://stackoverflow.com/questions/51466299/match-object-of-type-module

Avaq commented 6 years ago

You can do toString.call(module) === '[object Module]', or module && module[Symbol.toStringTag] === 'Module'.

loganfsmyth commented 6 years ago

I want to clarify that the Module object is just a generic language thing, it is not specific to dynamic import. It's the same object that you get by using a namespace import .e.g

import * as things from "foo";

Also it may not matter in your case, since I'm not familiar with this project, but JS bundlers do not polyfill the [object Module] toString behavior as far as I know.

mfidemraizer commented 6 years ago

@loganfsmyth This corner case is really challenging because sanctuary-def should type check it like a literal object but this would cause every object to type check too...