babel-plugin-tcomb icon indicating copy to clipboard operation
babel-plugin-tcomb copied to clipboard

Trying to understand $Reify

Open volkanunsal opened this issue 9 years ago • 1 comments

@gcanti Can you expand on the use case for the $Reify type? I was looking around for an example on how to use this, but couldn't find one.

volkanunsal avatar Jul 20 '16 17:07 volkanunsal

The use case is runtime type introspection, that is when you want to read the informations stored in your types.

When you write this:

type Credentials = {
  username: string,
  password: string
};

the Credentials identifier lives in "the world of types", that is it's not accessible from your JavaScript code, so normally this raises an error:

console.log(Credentials.meta) // throws ReferenceError: Credentials is not defined

when you use this plugin though your model is compiled to something like:

import _t from 'tcomb'

const Credentials = _t.interface({
  username: _t.String,
  password: _t.String
})

so now the Credentials identifier lives in "the world of values" and this works as expected:

console.log(Credentials.meta) // => Object {kind: "interface", props: Object, name: "Credentials", identity: true, strict: false}

BUT if you are using Flow you can't do that, since flow would complain:

src/index.js:8
  8: console.log(Credentials.meta)
                 ^^^^^^^^^^^ Credentials. type referenced from value position
  3: type Credentials = {
          ^^^^^^^^^^^ type Credentials

Flow doesn't like that you mix types with values. So in order to have access to runtime infos but also to please Flow there is this trick: using the $Reify type

import type { $Reify } from 'tcomb'

const ReifiedCredentials = (({}: any): $Reify<Credentials>)

// ok for Flow
console.log(ReifiedCredentials.meta) // => Object {kind: "interface", props: Object, name: "Credentials", identity: true, strict: false}

gcanti avatar Jul 21 '16 06:07 gcanti