Skip to content

Instantly share code, notes, and snippets.

@nmn
Last active November 3, 2017 12:25
Show Gist options
  • Save nmn/3d7bc1682ea7aad79a416ae901b3abc1 to your computer and use it in GitHub Desktop.
Save nmn/3d7bc1682ea7aad79a416ae901b3abc1 to your computer and use it in GitHub Desktop.
Magic Flow Type 1: $FunctionXValue —— A magic flow type that takes a function type that takes one arg, the type of that arg, and returns the return value type of the function.
/* @flow */
type $Function1<A, B> = (arg: A) => B;
type _Function1Value<A, B, F: $Function1<A, B>> = B; // eslint-disable-line
type $Function1Value<F: $Function1<*, *>, A> = _Function1Value<A, *, F>;
var toString = (value) => String(value)
var toNumber = (value) => parseFloat(value) || 0
type NumberXString = ((value: number) => string) & ((value: string) => number)
// var numberXString: NumberXString = (value: number | string) => {
// if (typeof value === 'string') {
// return 1
// }
// return String(value)
// }
type ToStringRetVal = $Function1Value<typeof toString, any>
type ToNumberRetVal = $Function1Value<typeof toNumber, any>
;(toString: (val: any) => ToStringRetVal)
declare var x: ToStringRetVal
declare var y: ToNumberRetVal
;(x: string)
// $ExpectError
;(x: boolean)
// $ExpectError
;(x: number)
;(y: number)
// $ExpectError
;(y: string)
function fnValueReturner<V, F: $Function1<V, any>> (fn: F, v: V): $Function1Value<F, V> {
return fn(v)
}
;(fnValueReturner(toString, 1234): string)
// $ExpectError
;(fnValueReturner(toString, 1234): number)
type ShouldBeNumber = $Function1Value<NumberXString, string>
declare var num: ShouldBeNumber
;(num: number)
// $ExpectError
;(num: string)
@freddi301
Copy link

Coul you create the same for extracting the argument type?
There is my try, but id doesn't work

function s2n(s: string): number { return 1 };

type $functionAB<A, B> = (a: A) => B;
type $functionABgetB<A, B, F: $functionAB<A, B>> = B;
type $FB<F: $functionAB<*, *>, X> = $functionABgetB<X, *, F>;
type $functionABgetA<B, A, F: $functionAB<A, B>> = A;
type $FA<F: $functionAB<*, *>, X> = $functionABgetA<X, *, F>;
declare var b: $FB<typeof s2n, any>;
declare var a: $FA<typeof s2n, any>;

;(b: number);
;(b: string); // this must error - OK

;(a: string);
;(a: number); // this must error - but doesn't

@nmn
Copy link
Author

nmn commented Feb 28, 2017

@freddi301 Sorry can't seem to make it work.

@freddi301
Copy link

in 0.58.0 we have $Call now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment