@@ -15,6 +15,10 @@ import {
1515 ComputeKit ,
1616 type ComputeKitOptions ,
1717 type ComputeOptions ,
18+ type ComputeFunctionRegistry ,
19+ type RegisteredFunctionName ,
20+ type FunctionInput ,
21+ type FunctionOutput ,
1822} from '@computekit/core' ;
1923
2024// ============================================================================
@@ -100,39 +104,48 @@ export interface UseComputeQueryOptions<TOutput> extends Omit<
100104 *
101105 * @example
102106 * ```tsx
103- * // First, register the function
104- * kit.register('fibonacci', (n: number) => {
105- * let a = 0, b = 1;
106- * for (let i = 2; i <= n; i++) [a, b] = [b, a + b];
107- * return b;
108- * });
107+ * // Basic usage with explicit types
108+ * const { data, isLoading } = useComputeQuery<number, number>('fibonacci', 50);
109109 *
110- * // Then use it in your component
111- * function Fibonacci({ n }: { n: number }) {
112- * const { data, isLoading, error } = useComputeQuery('fibonacci', n);
113- *
114- * if (isLoading) return <div>Computing...</div>;
115- * if (error) return <div>Error: {error.message}</div>;
116- * return <div>Result: {data}</div>;
117- * }
110+ * // With typed registry - types are inferred!
111+ * // declare module '@computekit/core' {
112+ * // interface ComputeFunctionRegistry {
113+ * // fibonacci: { input: number; output: number };
114+ * // }
115+ * // }
116+ * // const { data } = useComputeQuery('fibonacci', 50); // data is number
118117 * ```
119118 */
120- export function useComputeQuery < TInput , TOutput > (
119+ export function useComputeQuery <
120+ TName extends RegisteredFunctionName ,
121+ TInput = FunctionInput < TName extends string ? TName : never > ,
122+ TOutput = FunctionOutput < TName extends string ? TName : never > ,
123+ > (
121124 /** Name of the registered compute function */
122- name : string ,
125+ name : TName ,
123126 /** Input to pass to the function */
124- input : TInput ,
127+ input : TName extends keyof ComputeFunctionRegistry
128+ ? ComputeFunctionRegistry [ TName ] [ 'input' ]
129+ : TInput ,
125130 /** React Query and ComputeKit options */
126- options ?: UseComputeQueryOptions < TOutput >
131+ options ?: UseComputeQueryOptions <
132+ TName extends keyof ComputeFunctionRegistry
133+ ? ComputeFunctionRegistry [ TName ] [ 'output' ]
134+ : TOutput
135+ >
127136) {
137+ type ActualOutput = TName extends keyof ComputeFunctionRegistry
138+ ? ComputeFunctionRegistry [ TName ] [ 'output' ]
139+ : TOutput ;
140+
128141 const kit = useComputeKit ( ) ;
129142 const { computeOptions, ...queryOptions } = options ?? { } ;
130143
131- return useQuery < TOutput , Error > ( {
144+ return useQuery < ActualOutput , Error > ( {
132145 queryKey : [ 'compute' , name , input ] as const ,
133146 queryFn : async ( ) => {
134- const result = await kit . run ( name , input as never , computeOptions ) ;
135- return result as TOutput ;
147+ const result = await kit . run ( name , input , computeOptions ) ;
148+ return result as ActualOutput ;
136149 } ,
137150 ...queryOptions ,
138151 } ) ;
@@ -158,33 +171,45 @@ export interface UseComputeMutationOptions<TInput, TOutput> extends Omit<
158171 *
159172 * @example
160173 * ```tsx
161- * function ImageProcessor() {
162- * const { mutate, data, isPending, error } = useComputeMutation<ImageData, ImageData>('blur');
174+ * // Basic usage with explicit types
175+ * const { mutate, isPending } = useComputeMutation<ImageData, ImageData>('blur');
163176 *
164- * return (
165- * <div>
166- * <button onClick={() => mutate(imageData)} disabled={isPending}>
167- * {isPending ? 'Processing...' : 'Apply Blur'}
168- * </button>
169- * {data && <img src={data.url} />}
170- * </div>
171- * );
172- * }
177+ * // With typed registry - types are inferred!
178+ * // const { mutate } = useComputeMutation('blur');
179+ * // mutate(imageData); // input type enforced
173180 * ```
174181 */
175- export function useComputeMutation < TInput , TOutput > (
182+ export function useComputeMutation <
183+ TName extends RegisteredFunctionName ,
184+ TInput = FunctionInput < TName extends string ? TName : never > ,
185+ TOutput = FunctionOutput < TName extends string ? TName : never > ,
186+ > (
176187 /** Name of the registered compute function */
177- name : string ,
188+ name : TName ,
178189 /** React Query and ComputeKit options */
179- options ?: UseComputeMutationOptions < TInput , TOutput >
190+ options ?: UseComputeMutationOptions <
191+ TName extends keyof ComputeFunctionRegistry
192+ ? ComputeFunctionRegistry [ TName ] [ 'input' ]
193+ : TInput ,
194+ TName extends keyof ComputeFunctionRegistry
195+ ? ComputeFunctionRegistry [ TName ] [ 'output' ]
196+ : TOutput
197+ >
180198) {
199+ type ActualInput = TName extends keyof ComputeFunctionRegistry
200+ ? ComputeFunctionRegistry [ TName ] [ 'input' ]
201+ : TInput ;
202+ type ActualOutput = TName extends keyof ComputeFunctionRegistry
203+ ? ComputeFunctionRegistry [ TName ] [ 'output' ]
204+ : TOutput ;
205+
181206 const kit = useComputeKit ( ) ;
182207 const { computeOptions, ...mutationOptions } = options ?? { } ;
183208
184- return useMutation < TOutput , Error , TInput > ( {
185- mutationFn : async ( input : TInput ) => {
209+ return useMutation < ActualOutput , Error , ActualInput > ( {
210+ mutationFn : async ( input : ActualInput ) => {
186211 const result = await kit . run ( name , input as never , computeOptions ) ;
187- return result as TOutput ;
212+ return result as ActualOutput ;
188213 } ,
189214 ...mutationOptions ,
190215 } ) ;
@@ -210,31 +235,46 @@ export function useComputeMutation<TInput, TOutput>(
210235 *
211236 * const { useQuery, useMutation } = createComputeHooks(kit);
212237 *
213- * function MyComponent() {
214- * const { data } = useQuery('fibonacci', 50);
215- * return <div>{data}</div>;
216- * }
238+ * // With typed registry - types are inferred!
239+ * const { data } = useQuery('fibonacci', 50); // data is number
217240 * ```
218241 */
219242export function createComputeHooks ( kit : ComputeKit ) {
220243 return {
221244 /**
222245 * Query hook bound to this ComputeKit instance
223246 */
224- useQuery : < TInput , TOutput > (
225- name : string ,
226- input : TInput ,
227- options ?: Omit < UseComputeQueryOptions < TOutput > , 'computeOptions' > & {
247+ useQuery : <
248+ TName extends RegisteredFunctionName ,
249+ TInput = FunctionInput < TName extends string ? TName : never > ,
250+ TOutput = FunctionOutput < TName extends string ? TName : never > ,
251+ > (
252+ name : TName ,
253+ input : TName extends keyof ComputeFunctionRegistry
254+ ? ComputeFunctionRegistry [ TName ] [ 'input' ]
255+ : TInput ,
256+ options ?: Omit <
257+ UseComputeQueryOptions <
258+ TName extends keyof ComputeFunctionRegistry
259+ ? ComputeFunctionRegistry [ TName ] [ 'output' ]
260+ : TOutput
261+ > ,
262+ 'computeOptions'
263+ > & {
228264 computeOptions ?: ComputeOptions ;
229265 }
230266 ) => {
267+ type ActualOutput = TName extends keyof ComputeFunctionRegistry
268+ ? ComputeFunctionRegistry [ TName ] [ 'output' ]
269+ : TOutput ;
270+
231271 const { computeOptions, ...queryOptions } = options ?? { } ;
232272
233- return useQuery < TOutput , Error > ( {
273+ return useQuery < ActualOutput , Error > ( {
234274 queryKey : [ 'compute' , name , input ] as const ,
235275 queryFn : async ( ) => {
236- const result = await kit . run ( name , input as never , computeOptions ) ;
237- return result as TOutput ;
276+ const result = await kit . run ( name , input , computeOptions ) ;
277+ return result as ActualOutput ;
238278 } ,
239279 ...queryOptions ,
240280 } ) ;
@@ -243,18 +283,39 @@ export function createComputeHooks(kit: ComputeKit) {
243283 /**
244284 * Mutation hook bound to this ComputeKit instance
245285 */
246- useMutation : < TInput , TOutput > (
247- name : string ,
248- options ?: Omit < UseComputeMutationOptions < TInput , TOutput > , 'computeOptions' > & {
286+ useMutation : <
287+ TName extends RegisteredFunctionName ,
288+ TInput = FunctionInput < TName extends string ? TName : never > ,
289+ TOutput = FunctionOutput < TName extends string ? TName : never > ,
290+ > (
291+ name : TName ,
292+ options ?: Omit <
293+ UseComputeMutationOptions <
294+ TName extends keyof ComputeFunctionRegistry
295+ ? ComputeFunctionRegistry [ TName ] [ 'input' ]
296+ : TInput ,
297+ TName extends keyof ComputeFunctionRegistry
298+ ? ComputeFunctionRegistry [ TName ] [ 'output' ]
299+ : TOutput
300+ > ,
301+ 'computeOptions'
302+ > & {
249303 computeOptions ?: ComputeOptions ;
250304 }
251305 ) => {
306+ type ActualInput = TName extends keyof ComputeFunctionRegistry
307+ ? ComputeFunctionRegistry [ TName ] [ 'input' ]
308+ : TInput ;
309+ type ActualOutput = TName extends keyof ComputeFunctionRegistry
310+ ? ComputeFunctionRegistry [ TName ] [ 'output' ]
311+ : TOutput ;
312+
252313 const { computeOptions, ...mutationOptions } = options ?? { } ;
253314
254- return useMutation < TOutput , Error , TInput > ( {
255- mutationFn : async ( input : TInput ) => {
315+ return useMutation < ActualOutput , Error , ActualInput > ( {
316+ mutationFn : async ( input : ActualInput ) => {
256317 const result = await kit . run ( name , input as never , computeOptions ) ;
257- return result as TOutput ;
318+ return result as ActualOutput ;
258319 } ,
259320 ...mutationOptions ,
260321 } ) ;
@@ -269,5 +330,13 @@ export function createComputeHooks(kit: ComputeKit) {
269330// Exports
270331// ============================================================================
271332
272- export type { ComputeKitOptions , ComputeOptions } from '@computekit/core' ;
333+ export type {
334+ ComputeKitOptions ,
335+ ComputeOptions ,
336+ // Typed registry exports
337+ ComputeFunctionRegistry ,
338+ RegisteredFunctionName ,
339+ FunctionInput ,
340+ FunctionOutput ,
341+ } from '@computekit/core' ;
273342export { ComputeKit } from '@computekit/core' ;
0 commit comments