Even though Formik is using Typescript, it would still be great to have Flow type definitions added to the Flow-typed repository. By just adding a description of the Formik interface using Flow in this repository, Formik functions could be type checked in Flow projects also.
Automatic conversion could help with take off https://github.com/joarwilk/flowgen
FWIW, I generated a definition with flowgen and manually tweaked it to get things sort-of working here https://gist.github.com/jdelStrother/8227ce99250e366cd9963686f515278a
It successfully checks the call to Formik() - eg something like this would fail:
export default Formik({
})(SignupForm)
because handleSubmit wasn't defined.
However, it doesn't typecheck the component being wrapped - I can't figure out how to express something like this:
type SignupProps = {bannerMessage: string} & FormikProps
const SignupForm = ({bannerMessage, values, errors, etc}: SignupProps) => <div />
export default Formik({...})(SignupForm)
such that it would warn about missing bannerMessage in props.
HOCs with Flow are kinda issue right now. Will try to dig into this. Awesome work :)
Making some progress on this field, stay tuned 馃帀
Having a problem with typing main function.
My Typescript knowledge is very basic, what I understand this is possible
function Formik<Props, Values>(config: any) {
return b;
}
// you can specify those generics at call site
interface P {
email: string,
otherProp: number
}
interface V {
email: string
}
const enhancer = Formik<P, V>({/*...*/})
Unfortunately, you cannot specify generic at call site for Flow. Instead, they could be extracted from params.
function Formik<Props, Values>(param1: Props, param2: Values) {
return b;
}
interface P {
email: string,
otherProp: number
}
interface V {
email: string
}
const enhancer = Formik(props: P, values: V)
Any ideas how to solve this?
Stopping work on flow typings until new API is released as stable
@jdelStrother do you have an example of using this flow-typed in a code?
@sibelius I'm not sure what you're asking - there's this example, does that help?
type SignupProps = {bannerMessage: string} & FormikProps
const SignupForm = ({bannerMessage, values, errors, etc}: SignupProps) => <div />
export default Formik({...})(SignupForm)
there is no FormikProps in your flow-typed example
Guys I did good (I think) flow library definitions for formik
Here is it:
declare module 'formik' {
declare type UnaryFn<A, R> = (a: A) => R;
declare type Component<A> = React$ComponentType<A>;
declare export type HOC<Base, Enhanced> = UnaryFn<
Component<Base>,
Component<Enhanced>,
>;
declare export function Formik<Enhanced, Values>(
// Formik configuration options
options: {
displayName?: string,
mapPropsToValues?: (props: Enhanced) => Values,
handleSubmit?: (
values: Values,
formikBag: {
props: Enhanced,
setValues: (values: Values) => void,
setFieldValue: <K: $Keys<Values>>(field: K, value: any) => void,
setErrors: (errors: { [key: $Keys<Values>]: string }) => void,
setFieldError: <K: $Keys<Values>>(field: K, message: string) => void,
setTouched: (touched: { [key: $Keys<Values>]: boolean }) => void,
setFieldTouched: <K: $Keys<Values>>(
field: K,
isTouched?: boolean,
) => void,
setSubmitting: (isSubmitting: boolean) => void,
setStatus: (status: any) => void,
resetForm: (nextProps?: Enhanced) => void,
submitForm: () => void,
},
) => void,
validate?: (
values: Values,
props: Enhanced,
) =>
| void
| $ObjMap<Values, <K>(k: K) => string>
| Promise<void | $ObjMap<Values, <K>(k: K) => string>>,
validationSchema?: ((props: Enhanced) => any) | any,
validateOnChange?: boolean,
validateOnBlur?: boolean,
isInitialValid?: boolean | ((props: Enhanced) => boolean | void),
},
): HOC<
{
...$Exact<Enhanced>,
// FormikComputedProps
dirty: boolean,
isValid: boolean,
// Formik state and state helpers
values: Values,
setValues: (values: Values) => void,
setFieldValue: <K: $Keys<Values>>(field: K, value: any) => void,
errors: $ObjMap<Values, <K>(k: K) => ?string>,
setErrors: (errors: { [key: $Keys<Values>]: string }) => void,
setFieldError: <K: $Keys<Values>>(field: K, message: string) => void,
touched: $ObjMap<Values, <K>(k: K) => boolean | void>,
setTouched: (touched: { [key: $Keys<Values>]: boolean }) => void,
setFieldTouched: <K: $Keys<Values>>(
field: K,
isTouched?: boolean,
) => void,
isSubmitting: boolean,
setSubmitting: (isSubmitting: boolean) => void,
status?: any,
setStatus: (status: any) => void,
resetForm: (nextProps?: Enhanced) => void,
submitForm: () => void,
// FormikHandlers
handleSubmit: (e: SyntheticEvent<EventTarget>) => void,
handleChange: (e: SyntheticEvent<EventTarget>) => void,
handleChangeValue: (name: string, value: any) => void,
handleBlur: (e: SyntheticEvent<EventTarget>) => void,
handleReset: () => void,
},
Enhanced,
>;
}
It works well in combination with recompose HOCs, and uses the same usage idea
as described here and at medium article
So all you need to use it is to import HOC type and to declare formik enhancer with it
/* @flow */
import * as React from 'react';
import { Formik } from 'formik';
import type { HOC } from 'formik';
const myForm = ({
values,
errors,
handleChange,
setFieldError,
handleSubmit,
}) => (
<form onSubmit={handleSubmit}>
<input id="name" value={values.name} onChange={handleChange} />
<input id="age" value={values.age} onChange={handleChange} />
<div onClick={() => setFieldError('age', 'bad age')}>
{errors.name} {errors.age}
</div>
</form>
);
// The only type you need to define
type MyProps = {
someObj: {
name: string,
age: number,
},
};
const formikEnhancer: HOC<*, MyProps> = Formik({
mapPropsToValues: ({ someObj }) => ({
name: someObj.name,
age: someObj.age,
someStrangeValue: {
id: someObj.age,
},
}),
handleSubmit: (values, { props, setSubmitting, setFieldError }) => {
setSubmitting(true);
setFieldError('age', 'bad bad');
},
});
export default formikEnhancer(myForm);
Type inference work well see image

Errors detected well

Feel free to add this into flowtyped and contact me if you have any questions
@istarkov hey, you might be interested in following this one 馃槈
How about exporting types with "namespace", to prevent name collisions.
E.g. HOC => FormikHOC
@istarkov looks good
are you gonna send a PR do flow-typed repo?
I think FormikHOC would be a good name
Sorry guys have no time for PR, please make it
There will be no collision with names, u can change name on import
I also have version with typed status, but found it useless in current realisation (no ability to merge with prev) so decided not to provide it here
There will be no collision with names, u can change name on import
While that's true, would be explicit name better?
Can take care of PR if you're not against
@Andreyco thank you it will be great!
@Andreyco any updates?
I've started this here: https://github.com/flowtype/flow-typed/pull/1395
@aaronjensen could you take a look to this issue #696 ? Thanks!
@DTupalov sorry, I'm no longer using Formik nor Flow. Typing HoCs is way too challenging in flow (or at least it used to be, I'm not too interested in finding out if it's easier now...) Sorry, but good luck!
@aaronjensen sadly :(
@istarkov maybe you can help with advice in #696 issue?
I also switched to non hoc version of formik and use local defs defined here
https://github.com/jaredpalmer/formik/pull/591
Most helpful comment
Guys I did good (I think) flow library definitions for
formikHere is it:
It works well in combination with
recomposeHOCs, and uses the same usage ideaas described here and at medium article
So all you need to use it is to import HOC type and to declare formik enhancer with it
Type inference work well see image
Errors detected well
Feel free to add this into flowtyped and contact me if you have any questions