andreypopp / validated

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

Enums can probably be inferred properly now #21

Closed pronebird closed 6 years ago

pronebird commented 6 years ago

I am just testing some code with Flow 0.66 now and it seems it can in fact recognize the types in array:

function compose<A, B: Array<A>>(input: B): {[string]: A}  {
  var i = 0, obj = {};
  for(var value of input) {
    obj[i] = value;
    i++;
  }
  return obj;
}

var result = compose(['a', 1, 'c']);

At least in IDE I see that flow reports the right type:

{
    [string]: (string | number)
}

Given this while we still can't turn it into something meaningful such as 'A' | 'B' unions in Flow, but this allows for certain type checks on the Flow side at least.

So maybe enumeration function can be changed to:

export function enumeration<A, B: Array<A>>(...values: B): EnumerationNode<A> {
  let node: EnumerationNode<*> = new EnumerationNode(values);
  return node;
}

Just a quick test in IDE revealed that const protocols = enumeration('udp', 'tcp'); becomes:

EnumerationNode<string>

This is by far still better than mixed I guess. Can you confirm that it works for you or it's just VSCode that's messing with my head.

pronebird commented 6 years ago

Actually it's probably enough to do this:

export function enumeration<A>(...values: Array<A>): EnumerationNode<A> {
  return new EnumerationNode(values);
}
andreypopp commented 6 years ago

Released a fix which does the proposed changes:

function test_enum() {
  const schema: s.EnumerationNode<'a' | 'v'> = s.enumeration('a', 'v');
  const data = o.validate(schema, 'a');
  (data: 'a' | 'v');
  (data: string);
  // $ExpectError
  (data: number);
}
pronebird commented 6 years ago

@andreypopp thanks!

or maybe cast the input and spread it:

type UT = 'a' | 'v';
const schema = s.enumeration(
  ...(['a', 'v']: Array<UT>) ); // I wish they had $Values<UT> implemented
andreypopp commented 6 years ago

Yeah, that would be great, indeed if we have $TupleReduce...