【问题标题】:Can you check if an object conforms to a Flow type at runtime?你能在运行时检查一个对象是否符合 Flow 类型吗?
【发布时间】:2016-12-09 05:06:57
【问题描述】:

我有一个正在解析的 JSON 对象,我正在为输出编写测试,但我无法在运行时检查特定对象是否符合流类型。

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?
        })
    });
});

有什么方法可以实现吗?

【问题讨论】:

    标签: javascript unit-testing flowtype


    【解决方案1】:

    如果您的意思是在运行时使用流,答案肯定是否定的,流是用 ocaml 编写的。祝你好运从 JavaScript 调用它。如果您的意思是验证对象的属性类型,那么答案大部分是肯定的。您将不得不手动检查字段的类型。我会从这样的开始:

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

    确保对象具有正确的键。

    然后您必须检查这些键的值的类型是否正确。对于内置插件,这很容易:

    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
    

    等等。对于您自己通过 new 的构造函数创建的类型,我会使用:

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

    虽然这不是万无一失的,但它应该工作得很好。为了有点无耻的自我推销,我写了一个处理很多这类东西的小库,找到它here。也在npm

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        runtime-types project 看起来很有希望。

        来自自述文件,

        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' } ]
        

        【讨论】:

          【解决方案4】:

          我不知道为什么人们不更多地使用它,但是joi 是一个很棒的形状和类型验证库

          您可以定义任何对象形状,然后检查哪些对象符合要求。如果你想要一个类似断言的体验,你可以这样做

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-08-17
            • 2020-02-24
            • 1970-01-01
            • 2011-03-25
            • 1970-01-01
            • 1970-01-01
            • 2011-09-26
            相关资源
            最近更新 更多