Skip to content

Commit 73bf5f3

Browse files
fix: nested root keys typescript
1 parent 05b4620 commit 73bf5f3

File tree

4 files changed

+79
-14
lines changed

4 files changed

+79
-14
lines changed

example/src/App.tsx

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
import * as React from 'react';
22

33
import { View } from 'react-native';
4-
import { useFormState, Form } from '../../src/index';
5-
import { Button, HelperText, TextInput } from 'react-native-paper';
4+
import { Form, useFormState } from '../../src/index';
5+
import {
6+
Button,
7+
HelperText,
8+
Surface,
9+
TextInput,
10+
Title,
11+
} from 'react-native-paper';
612

13+
type AddressType = {
14+
street: string;
15+
houseNumber: string;
16+
};
717
type FormType = {
818
email: string;
919
telephone: string;
@@ -16,10 +26,7 @@ type FormType = {
1626
telephone: string;
1727
revenue: number;
1828
};
19-
address?: {
20-
street: string;
21-
houseNumber: string;
22-
};
29+
address?: AddressType;
2330
};
2431
export default function App() {
2532
const [
@@ -58,7 +65,9 @@ export default function App() {
5865
marginTop: 100,
5966
marginLeft: 12,
6067
marginRight: 12,
61-
// alignSelf: 'center',
68+
alignSelf: 'center',
69+
width: 300,
70+
paddingBottom: 500,
6271
}}
6372
>
6473
<Form {...formProps}>
@@ -175,6 +184,9 @@ export default function App() {
175184
<HelperText type="error" visible={hasError('organization.revenue')}>
176185
{errors.organization?.revenue}
177186
</HelperText>
187+
188+
<AddressEdit {...fh.raw('address')} />
189+
178190
<Button mode="contained" onPress={submit} style={{ marginTop: 24 }}>
179191
Save
180192
</Button>
@@ -183,15 +195,44 @@ export default function App() {
183195
);
184196
}
185197

198+
function AddressEdit({
199+
value,
200+
onChange,
201+
...rest
202+
}: {
203+
value: AddressType | undefined;
204+
onChange: (v: AddressType | undefined) => void;
205+
}) {
206+
const [{ formProps }, fh] = useFormState<AddressType>(
207+
value || { street: '', houseNumber: '' },
208+
{
209+
onChange,
210+
}
211+
);
212+
return (
213+
<Surface {...rest}>
214+
<Title>Nested form</Title>
215+
<Form {...formProps}>
216+
<TextInput
217+
mode="outlined"
218+
label="Street"
219+
{...fh.streetAddress('street')}
220+
/>
221+
<TextInput
222+
mode="outlined"
223+
label="House number"
224+
{...fh.streetAddress('houseNumber')}
225+
/>
226+
</Form>
227+
</Surface>
228+
);
229+
}
230+
186231
function looksLikeTelephone(str: string): boolean {
187232
if (str.length !== 10) {
188233
return false;
189234
}
190-
let isNum = /^\d+$/.test(str);
191-
if (!isNum) {
192-
return false;
193-
}
194-
return true;
235+
return /^\d+$/.test(str);
195236
}
196237

197238
function looksLikeMail(str: string): boolean {

src/objectPath.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ export function deepGet<V>(obj: any, path: any): V {
174174
return nextObj;
175175
}
176176

177-
return deepGet((obj as any)[currentPath], path.slice(1));
177+
return deepGet(obj[currentPath], path.slice(1));
178178
}
179179

180180
export const deepSet = set.bind(null, null);

src/types.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,29 @@ export type GetFieldType<T, P> = P extends `${infer Left}.${infer Right}`
3636
// https://stackoverflow.com/questions/58434389/typescript-deep-keyof-of-a-nested-object
3737

3838
export type DotPrefix<T extends string> = T extends '' ? '' : `.${T}`;
39+
// export type DotNestedKeysAndRoot<T> = (
40+
// T extends object
41+
// ? {
42+
// [K in Exclude<keyof T, symbol>]: `${K}${DotPrefix<
43+
// DotNestedKeys<T[K]>
44+
// >}`;
45+
// }[Exclude<keyof T, symbol>]
46+
// : ''
47+
// ) extends infer D
48+
// ? Extract<D, string>
49+
// : never;
50+
51+
export type DotNestedKeysWithRoot<T> = (
52+
T extends object
53+
? {
54+
[K in Exclude<keyof T, symbol>]:
55+
| `${K}${DotPrefix<DotNestedKeys<T[K]>>}`
56+
| `${K}`;
57+
}[Exclude<keyof T, symbol>]
58+
: ''
59+
) extends infer D
60+
? Extract<D, string>
61+
: never;
3962

4063
export type DotNestedKeys<T> = (
4164
T extends object

src/useFormState.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
DotNestedKeys,
1717
GetFieldType,
1818
TouchedUtility,
19+
DotNestedKeysWithRoot,
1920
} from './types';
2021

2122
type FormTextInputProps = {
@@ -62,7 +63,7 @@ type CustomizingRaw<V, T> = {
6263
onLayout?: TextInputProps['onLayout'];
6364
};
6465

65-
type FormRawType<T> = <K extends DotNestedKeys<T>>(
66+
type FormRawType<T> = <K extends DotNestedKeysWithRoot<T>>(
6667
key: K,
6768
handlers?: CustomizingRaw<GetFieldType<T, K>, T>
6869
) => FormRawProps<GetFieldType<T, K>>;

0 commit comments

Comments
 (0)