sigsve sigsve - 4 months ago 20
Javascript Question

Can you check if an object conforms to a Flow type at runtime?

I have a JSON object that is being parsed, and I'm writing tests for the output and I wan't to be able to check if a specific object conforms to a flow type, at runtime.

const object = {/**/}

type SomeType = {
foo: string,
bar: bool,
baz: Object,
}

describe('object', () => {
describe('.subfield', () => {
it('conforms to SomeType', () => {
// Here I want to write an 'expect'
// that checks if object.subfield
// conforms to the SomeType flow type?
})
});
});


Is there any way this is achievable?

Answer

If you mean use flow at runtime, the answer is definitively no, flow is written in ocaml. Good luck calling that from JavaScript. If you mean verify the types of the properties of an object, the answer is, for the most part, yes. You will have to manually check the types of the fields. I would start with something like this:

let expectedKeys = ['foo', 'bar', 'baz'].sort().toString();
expect(Object.keys(testObj).sort().toString()).toBe(expectedKeys);

To make sure the object has the proper keys.

Then you will have to check if the types of the values at those keys are correct. For built-ins, this is easy:

const _extractHiddenClass = (r => a => {
  return Object.prototype.toString.call(a).match(r)[1].toLowerCase();
})(/ ([a-z]+)]$/i);

_extractHiddenClass(/inrst/i); // regexp
_extractHiddenClass(true);     // boolean
_extractHiddenClass(null);     // null

And so on. For your own types made via a constructor with new I'd use:

const _instanceOf = (ctor, obj) => {
  return (obj instanceof ctor) || 
   (ctor.name && ctor.name === obj.constructor.name);
};

Although this isn't totally foolproof, it should work well enough. And for a bit of shameless self-promotion, I wrote a little library that handles a lot of this kind of stuff, find it here. Also on npm.