Description
I saw your note saying there is an unknown
type somewhere in JSError but I couldn't find it or determine if it resolves the issue here. I've been experimenting with some code that makes use of the unknown
type. Below is an example. Notice the syntax error at the very bottom. Is it possible to create an unknown
type that you can safely assign anything to without requiring the developer to do something like Unknown.make
? In TypeScript there are two top-types any
and unknown
(see here). In ReScript whenever I see 'a
that looks like any
to me. I've seen ReScript type definitions that use something like <+'a>
and thought maybe that technique would help but I don't understand it.
In the example below, I want developers to author instances of Pattern
. It is safest to author these when isTypeOf
takes an Unknown.t
because if it were just an 'a
then the developer, if not careful, could treat the function parameter like a string or anything when it really isn't, and this can cause run-time crashes. But when using a Pattern
I want to be able to pass in anything and not have to manually covert it to unknown using Unknown.make
which is kind of weird. So from inside the isTypeOf
the parameter should look like Unknown.t
but when calling it from the outside I want it to accept an 'an any
.
If this isn't possible, I wonder if we should have a unknown
top-level type exposed in the language. This would be useful to provide more safe external functions; make them return an unknown
if we don't know exactly what we're going to get. We could use this in Object
module of Core
when we're getting property values. And maybe genType exports these as unknown
without any shims.
module Unknown = {
type t
external make: 'a => t = "%identity"
}
module type Pattern = {
type t
let isTypeOf: Unknown.t => bool
}
module NonEmptyString: Pattern = {
type t = string
let isTypeOf = (u: Unknown.t) =>
switch u->Js.Types.classify {
| Js.Types.JSString(s) => s->Js.String2.trim->Js.String2.length > 0
| _ => false
}
// Unsafe and unpredictable if not a string
// let isTypeOfUnsafe = u => u->Js.String2.trim->Js.String2.length > 0
}
let x = 45->Unknown.make->NonEmptyString.isTypeOf // Works but weird
let y = 45->NonEmptyString.isTypeOf // Syntax error!