gajus / gajus/flow-runtime

Is it possible to check if a JSON object validates against all properties of my class definition?

Open
#154 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
797
Forks
49
PR merge metrics
No merged PRs in 30d

Description

This is a:

- [ ] Bug Report
- [ ] Feature Request
- [X] Question
- [ ] Other

Which concerns:

- [X] flow-runtime
- [X] babel-plugin-flow-runtime
- [ ] flow-runtime-validators
- [ ] flow-runtime-mobx
- [ ] flow-config-parser
- [ ] The documentation website

---

### What is the current behaviour?

I'm banging my head against the wall for a couple of hours now (yes, it hurts!). I'm trying to implement a validation for JSON objects. I have a class like:
```js
import _ from "lodash";

class MySchema {
foo: string;
bar: string;

assign(payload: Object) {
_.assign(this, payload);
}

doSomething() { ... };
doSomethingElse() { ... };
}
```

In the `MySchema#assign` above I'm now trying to validate a plain object `payload = { foo: "foo", bar: "bar" }` against that class definition. I've tried a couple of different approaches without much success:

This code only checks that the payload is an instance of `MySchema`, but doesn't check the properties `foo` and `bar` for validity.
```js
const schemaValidator = (reify: Type< MySchema >);
schemaValidator.assert(_.assign(new MySchema(), payload));
```

There's little documentation but `$Shape` looked like something useful. Unfortunately the following code just throws an "Can only $Shape object types." exception:
```js
const schemaValidator = (reify: Type< $Shape< MySchema > >);
schemaValidator.assert(payload);
```

The validation works as expected if I change `MySchema` to a `type` instead of a `class`. But obviously that's not what I want as I'd like to provide additional functions (`#doSomething` and `#doSomethingElse`) in the class instance. There seems to be no way in Flow to have a class inherit from a Type.

Another way I found is to define `MySchema` as an interface instead of a class, but this makes me repeat all properties in the actual class implementation like this:
```js
interface MySchema {
foo: string;
bar: string;
}

class MyEntity implements MySchema {
foo: string; // <-- I have to duplicate all properties here
bar: string; // <-- yuck

doSomething() { ... };
doSomethingElse() { ... };
}

// But at least the validation seems to work now...
const schemaValidator = (reify: Type< MySchema >);
schemaValidator.assert(payload);
```

I had plenty of other iterations but can't get it to really work intuitively.

---

### What is the expected behaviour?

I would hope to find a simple way of validating that my JSON object is indeed "compatible" with my class definition. Is that possible?

---

### Which package versions are you using?
```
├── babel-plugin-flow-runtime@0.11.1
├── babel-preset-flow@6.23.0
├── eslint-plugin-flow-check@1.1.1
├── eslint-plugin-flowtype@2.35.1
├── flow-bin@0.54.1
├── flow-runtime@0.14.0
├── flow-typed@2.1.5
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.