diff --git a/src/namePathType.ts b/src/namePathType.ts index 67a0245f..ee6d0022 100644 --- a/src/namePathType.ts +++ b/src/namePathType.ts @@ -13,18 +13,26 @@ export type DeepNamePath< ? ParentNamePath['length'] extends 0 ? Store | BaseNamePath // Return `BaseNamePath` instead of array if `ParentNamePath` is empty : Store extends any[] - ? [...ParentNamePath, number] // Connect path + ? readonly [...ParentNamePath, number] // Connect path : never : Store extends any[] // Check if `Store` is `any[]` ? // Connect path. e.g. { a: { b: string }[] } // Get: [a] | [ a,number] | [ a ,number , b] - [...ParentNamePath, number] | DeepNamePath + readonly [...ParentNamePath, number] | DeepNamePath : { // Convert `Store` to . We mark key a `FieldKey` [FieldKey in keyof Store]: Store[FieldKey] extends Function ? never : | (ParentNamePath['length'] extends 0 ? FieldKey : never) // If `ParentNamePath` is empty, it can use `FieldKey` without array path - | [...ParentNamePath, FieldKey] // Exist `ParentNamePath`, connect it + | readonly [...ParentNamePath, FieldKey] // Exist `ParentNamePath`, connect it | DeepNamePath[FieldKey], [...ParentNamePath, FieldKey]>; // If `Store[FieldKey]` is object }[keyof Store]; + +export type GetNameType< + Store = any, + NamePath extends readonly any[] = [], + NamePathCache extends readonly any[] = [], +> = NamePathCache['length'] extends NamePath['length'] + ? Store + : GetNameType; diff --git a/src/useWatch.ts b/src/useWatch.ts index 23c41bc6..6db10fbc 100644 --- a/src/useWatch.ts +++ b/src/useWatch.ts @@ -11,6 +11,7 @@ import type { import { useState, useContext, useEffect, useRef, useMemo } from 'react'; import { getNamePath, getValue } from './utils/valueUtil'; import { isFormInstance } from './utils/typeUtil'; +import type { DeepNamePath, GetNameType } from './namePathType'; type ReturnPromise = T extends Promise ? ValueType : never; type GetGeneric = ReturnPromise>; @@ -37,39 +38,15 @@ const useWatchWarning = : () => {}; function useWatch< - TDependencies1 extends keyof GetGeneric, - TForm extends FormInstance, - TDependencies2 extends keyof GetGeneric[TDependencies1], - TDependencies3 extends keyof GetGeneric[TDependencies1][TDependencies2], - TDependencies4 extends keyof GetGeneric[TDependencies1][TDependencies2][TDependencies3], + TForm extends FormInstance = FormInstance, + const TDependencies extends DeepNamePath> = any, >( - dependencies: [TDependencies1, TDependencies2, TDependencies3, TDependencies4], + dependencies: TDependencies, form?: TForm | WatchOptions, -): GetGeneric[TDependencies1][TDependencies2][TDependencies3][TDependencies4]; - -function useWatch< - TDependencies1 extends keyof GetGeneric, - TForm extends FormInstance, - TDependencies2 extends keyof GetGeneric[TDependencies1], - TDependencies3 extends keyof GetGeneric[TDependencies1][TDependencies2], ->( - dependencies: [TDependencies1, TDependencies2, TDependencies3], - form?: TForm | WatchOptions, -): GetGeneric[TDependencies1][TDependencies2][TDependencies3]; - -function useWatch< - TDependencies1 extends keyof GetGeneric, - TForm extends FormInstance, - TDependencies2 extends keyof GetGeneric[TDependencies1], ->( - dependencies: [TDependencies1, TDependencies2], - form?: TForm | WatchOptions, -): GetGeneric[TDependencies1][TDependencies2]; - -function useWatch, TForm extends FormInstance>( - dependencies: TDependencies | [TDependencies], - form?: TForm | WatchOptions, -): GetGeneric[TDependencies]; +): GetNameType< + GetGeneric, + TDependencies extends readonly any[] ? TDependencies : [TDependencies] +>; function useWatch( dependencies: [], diff --git a/tests/useWatch.test.tsx b/tests/useWatch.test.tsx index 6e22819b..53103121 100644 --- a/tests/useWatch.test.tsx +++ b/tests/useWatch.test.tsx @@ -258,7 +258,7 @@ describe('useWatch', () => { demo?: string; demo2?: string; id?: number; - demo1?: { demo2?: { demo3?: { demo4?: string } } }; + demo1?: { demo2?: { demo3?: { demo4?: { demo5?: { demo6: { demo7?: string } } } } } }; }; const Demo: React.FC = () => { @@ -271,10 +271,28 @@ describe('useWatch', () => { const demo3 = Form.useWatch(['demo1', 'demo2', 'demo3'], form); const demo4 = Form.useWatch(['demo1', 'demo2', 'demo3', 'demo4'], form); const demo5 = Form.useWatch(['demo1', 'demo2', 'demo3', 'demo4', 'demo5'], form); - const more = Form.useWatch(['age', 'name', 'gender'], form); + const demo6 = Form.useWatch(['demo1', 'demo2', 'demo3', 'demo4', 'demo5', 'demo6'], form); + const demo7 = Form.useWatch( + ['demo1', 'demo2', 'demo3', 'demo4', 'demo5', 'demo6', 'demo7'], + form, + ); const demo = Form.useWatch(['demo']); return ( - <>{JSON.stringify({ values, main, age, demo1, demo2, demo3, demo4, demo5, more, demo })} + <> + {JSON.stringify({ + values, + main, + age, + demo1, + demo2, + demo3, + demo4, + demo5, + demo6, + demo7, + demo, + })} + ); };