andreypopp / validated

Validate your configurations with precise error messages
91 stars 14 forks source link

add Node.type field #16

Closed jey closed 6 years ago

jey commented 6 years ago

This adds a Node.type field to be used with Flow's typeof operator. For example:

const PersonFields = partialObject({ name: string, age: number, email: string });
type Person = typeof PersonFields.type;
const user: Person = validate(PersonFields, input);

This is modeled after a similar feature in https://github.com/freddi301/flow-validator.

andreypopp commented 6 years ago

Wow, didn't know it works like that. Can you add an example to test_flow.js so we don't regress on it later.

I think this also introduces an unsoundness as PersonFields.type doesn't have a value but you can access it and flow would be ok with that...

andreypopp commented 6 years ago

I wonder if

type _ExtractType<V, N: Node<V>> = V;
type ExtractType<N: Node<*>> = _ExtractType<*, N>

const PersonFields = partialObject({ name: string, age: number, email: string });
type Person = ExtractType<typeof PersonFields>;
const user: Person = validate(PersonFields, input);

could work instead.

jey commented 6 years ago

Neat, that's an elegant solution. Unfortunately this doesn't work for me on any of the versions I tried, including 0.55.0, which gives me the errors:

Error: src/proto/poll.js:37
 37: type Person = ExtractType<typeof PersonFields>;
                               ^^^^^^^^^^^^^^^^^^^ type application of polymorphic type: class type: Node. Expected polymorphic type instead of
 33: type _ExtractType<V, N: Node<V>> = V;
                             ^^^^^^^ class type: Node

Error: src/proto/poll.js:37
 37: type Person = ExtractType<typeof PersonFields>;
                               ^^^^^^^^^^^^^^^^^^^ type application of polymorphic type: class type: Node. Expected polymorphic type instead of
 34: type ExtractType<N: Node<*>> = _ExtractType<*, N>
                         ^^^^^^^ class type: Node

Found 2 errors
error Command failed with exit code 2.

Maybe this is related to Flow's $ObjMap issues (e.g. https://github.com/facebook/flow/issues/2674 and https://github.com/facebook/flow/issues/3387)?

andreypopp commented 6 years ago

Strange, it works for me, I've added this to test_flow.js in the repo:

function test_extract_type() {
  // type alias to extract type from a validator
  type _ExtractType<V, N: s.Node<V>> = V;
  type ExtractType<N: s.Node<*>> = _ExtractType<*, N>;

  // define type
  const PersonFields = s.partialObject({name: s.string, age: s.number, email: s.string});

  // this is how to extract type from a validator
  type Person = ExtractType<typeof PersonFields>;

  // assert that types are unified
  const user: Person = o.validate(PersonFields, '');
  const name: string = user.name;
  // $ExpectError
  const invalid: number = user.name;
}
andreypopp commented 6 years ago

You probably didn't import the correct type from validated and your Node thus points to Flow's built-in type for DOM. This is the origin of your error, I think.

andreypopp commented 6 years ago

Anyway, I think ExtractType is a good addition to validated, can you make a PR which adds it? Do you think ExtractType is a good name for such utility type? Another suggestions for the name: ValidatedType<Node>, ValidatedOf<Node>, ValueType<Node>...

jey commented 6 years ago

I like your solution! I'll just close this PR.

Please do add your elegant solution to the repo :)