rescript-core icon indicating copy to clipboard operation
rescript-core copied to clipboard

Getting data out of an Error, easier classifying unknown values, "Type" module thoughts

Open jmagaram opened this issue 1 year ago • 12 comments

I'm trying to do something simple. I caught a Firebase exception and want to access the code property that is a string. Firebase errors have code properties with contents like "auth/email-password-invalid". How can I do that? Here is one awkward way. Is there a simpler way?

@get_index external getErrorProperty: (Error.t, string) => option<'a> = ""

let toString1 = i =>
  switch i->Type.Classify.classify {
  | String(s) => Some(s)
  | _ => None
  }

let printError = (err: Error.t) =>
  err
  ->getErrorProperty("code")
  ->toString1
  ->Option.getWithDefault("No code found in the exception")
  ->Console.log

I think it would be useful to access arbitrary properties on Error.t just like I can on Object.t. I also want a much easier way to work with those values and not have to switch on Type.Classify.classify.

First idea is to add an Error.get function just like we have Object.get. This would be very convenient.

Second idea is to add convenience methods for classify like this. All these do is wrap the classify function with a Switch.

  let classify: 'a => classified
  let toString: 'a => option<string>
  let toFloat: 'a => option<float>

The third idea is to rename the Type module to Unknown and have an unknown type. When we have functions that return some unknown thing we could label them explicitly as unknown and the developer will then know they can use the Unknown module to classify and make sense of it. The rescript-struct module defines as unknown type that is used for serialization output. https://github.com/DZakh/rescript-struct#sserializewith TypeScript has an unknown type. The Object.get function returns an option<'a> which is too permissive because you can Option.map it and start treating it like something it is not and get a runtime error. So Object.get should return an option<unknown> and force the developer to safely inspect and classify it.

Finally and some random thoughts on the Type module.

  • It won't classify a bigint.
  • The classify symbol doesn't result in a Symbol.t - it is a Type.Classify.symbol
  • The classification method uses toString. Why not typeof? Wouldn't that be more efficient?
  • For a tiny module it is kind of annoying having a Classify sub-module just to hold the classify function. Couldn't this all be flattened out?

jmagaram avatar Mar 16 '23 18:03 jmagaram