Update FieldArray to type custom field arrays correctly (#35723)

This commit is contained in:
m-b-davis 2019-06-04 21:09:52 +01:00 committed by Andrew Casey
parent 1bc579b8e7
commit 3e7758937b
5 changed files with 61 additions and 34 deletions

View File

@ -7,6 +7,7 @@
// Alex Young <https://github.com/alsiola>
// Anton Novik <https://github.com/tehbi4>
// Huw Martin <https://github.com/huwmartin>
// Matt Davis <https://github.com/m-b-davis>
// Ethan Resnick <https://github.com/ethanresnick>
// Tim de Koning <https://github.com/reggino>
// Maddi Joyce <https://github.com/maddijoyce>

View File

@ -1,29 +1,30 @@
import { Component, ComponentType } from "react";
import { Validator } from "../index";
export interface BaseFieldArrayProps<P = {}> {
interface _BaseFieldArrayProps<P = {}, FieldValue = any> {
name: string;
component: ComponentType<P>;
component: ComponentType<WrappedFieldArrayProps<FieldValue> & P>;
validate?: Validator | Validator[];
warn?: Validator | Validator[];
forwardRef?: boolean;
props?: P;
withRef?: boolean;
rerenderOnEveryChange?: boolean;
}
export interface GenericFieldArray<Field, P = {}> extends Component<BaseFieldArrayProps<P> & Partial<P>> {
export type BaseFieldArrayProps<P = {}, FieldValue = any> = (P | { props: P}) & _BaseFieldArrayProps<P, FieldValue>;
export interface GenericFieldArray<FieldValue = any, P = {}> extends Component<BaseFieldArrayProps<P, FieldValue>> {
name: string;
valid: boolean;
getRenderedComponent(): Component<WrappedFieldArrayProps<Field> & P>;
getRenderedComponent(): Component<WrappedFieldArrayProps<FieldValue> & P>;
}
export class FieldArray<P = {}> extends Component<BaseFieldArrayProps<P> & Partial<P>> implements GenericFieldArray<any, P> {
export class FieldArray<P = {}, FieldValue = any> extends Component<BaseFieldArrayProps<P, FieldValue>> implements GenericFieldArray<FieldValue, P> {
name: string;
valid: boolean;
getRenderedComponent(): Component<WrappedFieldArrayProps<any> & P>;
getRenderedComponent(): Component<WrappedFieldArrayProps<FieldValue> & P>;
}
export interface WrappedFieldArrayProps<FieldValue> {
export interface WrappedFieldArrayProps<FieldValue = any> {
fields: FieldArrayFieldsProps<FieldValue>;
meta: FieldArrayMetaProps;
}
@ -35,12 +36,13 @@ export interface FieldArrayFieldsProps<FieldValue> {
get(index: number): FieldValue;
getAll(): FieldValue[];
removeAll(): void;
insert(index: number, value: FieldValue): void;
name: string;
length: number;
map<R>(callback: FieldIterate<FieldValue, R>): R[];
pop(): FieldValue;
push(value?: FieldValue): void;
push(value: FieldValue): void;
remove(index: number): void;
shift(): FieldValue;
swap(indexA: number, indexB: number): void;

View File

@ -160,7 +160,7 @@ const FieldsCustom = Fields as new () => GenericFields<MyFieldsCustomProps>;
/* FieldArray */
const MyArrayField: React.StatelessComponent = ({
const MyArrayField: React.StatelessComponent<WrappedFieldArrayProps> = ({
children
}) => null;
@ -169,20 +169,19 @@ const MyArrayField: React.StatelessComponent = ({
interface MyFieldValue {
num: number;
}
interface MyFieldArrayCustomProps {
foo: string;
bar: number;
}
const MyCustomArrayField: React.StatelessComponent<MyFieldArrayCustomProps> = ({
const MyCustomArrayField: React.StatelessComponent<MyFieldArrayCustomProps & WrappedFieldArrayProps<MyFieldValue>> = ({
children,
foo
fields,
foo,
bar
}) => null;
type MyFieldArrayProps = MyFieldArrayCustomProps & WrappedFieldArrayProps<MyFieldValue>;
const MyFieldArray: React.StatelessComponent<MyFieldArrayProps> = ({
children,
fields
}) => null;
const FieldArrayCustom = FieldArray as new () => GenericFieldArray<MyFieldValue, MyFieldArrayCustomProps>;
/* Tests */
@ -329,10 +328,22 @@ const Test = reduxForm<TestFormData>({
component={ MyArrayField }
/>
{/* Passing child props via explicit props arg (TS-preferable)*/}
<FieldArrayCustom
name="field10"
component={ MyCustomArrayField }
props={{
foo: 'bar',
bar: 123
}}
/>
{/* Passing child props via extra props passed to parent */}
<FieldArrayCustom
name="field10"
component={ MyCustomArrayField }
foo="bar"
bar={23}
/>
</FormSection>
</FormCustom>

View File

@ -1,29 +1,30 @@
import { Component, ComponentType } from "react";
import { Validator } from "../index";
export interface BaseFieldArrayProps<P = {}> {
interface _BaseFieldArrayProps<P = {}, FieldValue = any> {
name: string;
component: ComponentType<P>;
component: ComponentType<WrappedFieldArrayProps<FieldValue> & P>;
validate?: Validator | Validator[];
warn?: Validator | Validator[];
withRef?: boolean;
props?: P;
rerenderOnEveryChange?: boolean;
}
export interface GenericFieldArray<Field, P = {}> extends Component<BaseFieldArrayProps<P> & Partial<P>> {
export type BaseFieldArrayProps<P = {}, FieldValue = any> = (P | { props: P}) & _BaseFieldArrayProps<P, FieldValue>;
export interface GenericFieldArray<FieldValue = any, P = {}> extends Component<BaseFieldArrayProps<P, FieldValue>> {
name: string;
valid: boolean;
getRenderedComponent(): Component<WrappedFieldArrayProps<Field> & P>;
getRenderedComponent(): Component<WrappedFieldArrayProps<FieldValue> & P>;
}
export class FieldArray<P = {}> extends Component<BaseFieldArrayProps<P> & Partial<P>> implements GenericFieldArray<any, P> {
export class FieldArray<P = {}, FieldValue = any> extends Component<BaseFieldArrayProps<P, FieldValue>> implements GenericFieldArray<FieldValue, P> {
name: string;
valid: boolean;
getRenderedComponent(): Component<WrappedFieldArrayProps<any> & P>;
getRenderedComponent(): Component<WrappedFieldArrayProps<FieldValue> & P>;
}
export interface WrappedFieldArrayProps<FieldValue> {
export interface WrappedFieldArrayProps<FieldValue = any> {
fields: FieldArrayFieldsProps<FieldValue>;
meta: FieldArrayMetaProps;
}
@ -35,6 +36,7 @@ export interface FieldArrayFieldsProps<FieldValue> {
get(index: number): FieldValue;
getAll(): FieldValue[];
removeAll(): void;
insert(index: number, value: FieldValue): void;
name: string;
length: number;

View File

@ -160,7 +160,7 @@ const FieldsCustom = Fields as new () => GenericFields<MyFieldsCustomProps>;
/* FieldArray */
const MyArrayField: React.StatelessComponent = ({
const MyArrayField: React.StatelessComponent<WrappedFieldArrayProps> = ({
children
}) => null;
@ -171,18 +171,16 @@ interface MyFieldValue {
}
interface MyFieldArrayCustomProps {
foo: string;
bar: number;
}
const MyCustomArrayField: React.StatelessComponent<MyFieldArrayCustomProps> = ({
const MyCustomArrayField: React.StatelessComponent<MyFieldArrayCustomProps & WrappedFieldArrayProps<MyFieldValue>> = ({
children,
foo
fields,
foo,
bar
}) => null;
type MyFieldArrayProps = MyFieldArrayCustomProps & WrappedFieldArrayProps<MyFieldValue>;
const MyFieldArray: React.StatelessComponent<MyFieldArrayProps> = ({
children,
fields
}) => null;
const FieldArrayCustom = FieldArray as new () => GenericFieldArray<MyFieldValue, MyFieldArrayCustomProps>;
/* Tests */
@ -329,11 +327,24 @@ const Test = reduxForm<TestFormData>({
component={ MyArrayField }
/>
{/* Passing child props via explicit props arg (TS-preferable)*/}
<FieldArrayCustom
name="field10"
component={ MyCustomArrayField }
props={{
foo: 'bar',
bar: 123
}}
/>
{/* Passing child props via extra props passed to parent */}
<FieldArrayCustom
name="field10"
component={ MyCustomArrayField }
foo="bar"
bar={23}
/>
</FormSection>
</FormCustom>
</div>