Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 233
SomeNorwegianGuy Avatar asked Aug 03 '16 12:08

SomeNorwegianGuy


People also ask

How do I know my runtime type?

Using validation libraries io-ts is a runtime type checking library that provides utility methods to perform data validation and encodes/decodes the data being parsed. io-ts is essentially used to streamline data operations in TypeScript for runtime type checking.

What is flow syntax?

To bring static typing to JavaScript, Flow specifies a number of syntax extensions, which are used to describe types, annotate programs, and share types between modules. Flow's syntax extensions are only additions which can be easily stripped away and don't change the runtime behavior of JavaScript in any way.

What is flow and TypeScript?

Both Flow and TypeScript provide the ability to explicitly cast a variable from one type to another. With Flow, we cast using the symbol : , while in TypeScript we cast using the keyword as . // TypeScript let value = 1 as number; // Flow let value = 1; (value: number);


1 Answers

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.

like image 53
Jared Smith Avatar answered Nov 13 '22 18:11

Jared Smith