Skip to content

Should we have an unknown top-level type #6119

Closed
@jmagaram

Description

@jmagaram

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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions