简体   繁体   中英

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?

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 .

检查https://codemix.github.io/flow-runtime用于JavaScript的与流兼容的运行时类型系统。

The runtime-types project looks promising.

From the README,

example-types.js

// @flow
export type PhoneNumber = string;

export type User = {
  username: string;
  age: number;
  phone: PhoneNumber;
  created: ?Date;
}

validator.js

var types = require('runtime-types')
var validate = require('runtime-types').validate

var MyTypes = types.readFile(path.join(__dirname, '../test/example-types.js'))

var VALIDATORS = {
  PhoneNumber: validate.validateRegex(/^\d{10}$/),
}

var validators = validate.createAll(VALIDATORS, MyTypes)

var errs = validators.User({
  age: 23,
  phone: "8014114399"
})

// ==> [ { key: 'username', value: undefined, error: 'missing' } ]

I don't know why people do not use it more, but joi is a fantastic shape and type validation library

You can define any object shape and then just check which objects conforms. If you want an assertion like experience you can do it like this

const schema = joi.object().keys({a:joi.string()});
joi.assert(myObj,schema,"error message") 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM