tcomb icon indicating copy to clipboard operation
tcomb copied to clipboard

Improve documentation

Open gcanti opened this issue 9 years ago • 6 comments

I'm writing "A little guide to runtime type checking and runtime type introspection" https://github.com/gcanti/tcomb/blob/master/docs/GUIDE.md. It's an attempt to write down how I use tcomb in my own projects, hope it's helpful to others. Any comment, suggestion or review is welcome.

Cheers, Giulio

gcanti avatar Jan 06 '16 16:01 gcanti

Very helpful, especially the last section on converting Dates, as I've been looking at jsonapi, also id fields are serialized as a string instead of an integer (I wonder if there's an idea for another tcomb library variant in the future? - at the moment I'm using https://github.com/beauby/jsonapi-datastore to parse the responses).

Anyway, in my scenario I found a few issues with the deserialise function:

  • I needed to override fromJSON on a refinement (subtype).
  • list was missing.
  • unknown props would throw an error, rather than be ignored as with normal construction.

Here's my version (uses Babel):

t.Date.fromJSON = (s) => s ? new Date(s) : null // allow conversion from ISO-8601

// Deserialize to tcomb type, allows for conversions via a fromJSON function on the type.
export const deserialize = (value, type) => {
  // Ignore unknown types, probably extra data that will be ignored anyway.
  if (!type) {
    return value
  }

  const { kind } = type.meta
  switch (kind) {
    case 'struct':
      return type(Object.keys(value).reduce((acc, key) => {
        acc[key] = deserialize(value[key], type.meta.props[key])
        return acc
      }, {}))
    case 'list':
      return type(value.map((element) => deserialize(element, type.meta.type)))
    case 'maybe':
      return deserialize(value, type.meta.type)
    case 'subtype': // the kind of refinement is 'subtype' (for legacy reasons)
      // See if custom serializer, else delegate to supertype.
      if (t.Function.is(type.fromJSON)) {
        return type.fromJSON(value)
      }
      return deserialize(value, type.meta.type)
    case 'enums':
    case 'irreducible':
      if (t.Function.is(type.fromJSON)) {
        return type.fromJSON(value)
      }
      return value
  }
}

Maybe the maybe case should handle null, rather than my t.Date.fromJSON example?

Are there any other types that should be handled? Should the default case throw an error or return value?

grahamlyus avatar Jan 19 '16 22:01 grahamlyus

Hi @grahamlyus,

The deserialize function is just an example of RTI, it doesn't mean to be complete, but I should mention that, thanks for pointing out!

Are there any other types that should be handled?

Technically tuple, dict, intersection and union are missing.

For a complete implementation, which is very interesting, I opened a issue here https://github.com/gcanti/tcomb/issues/169

gcanti avatar Jan 20 '16 07:01 gcanti

it doesn't mean to be complete

However how I'm handling maybe is not good, so I amended the example in GUIDE.md

gcanti avatar Jan 20 '16 08:01 gcanti

Is there a quick method to disable runtime checking without needing to run in NODE_ENV=production?

marwanhilmi avatar Jan 26 '16 05:01 marwanhilmi

@marwanhilmi not that I'm aware. May I ask you what's your use case?

gcanti avatar Jan 26 '16 06:01 gcanti

We use NODE_ENV to toggle our config, ie NODE_ENV=staging so it would be nice to have another option to disable runtime checking without specifically checking for production. Perhaps its own env flag?

marwanhilmi avatar Jan 26 '16 06:01 marwanhilmi