如何实现接收Lambda及命名参数的TypeScript函数?
实现支持Lambda函数+结构化参数的通用函数(适配React请求钩子场景)
核心思路
针对你需要的foo(lambdaFn, { param1: "test", param2: 1})调用方式,通过泛型约束Lambda的参数类型,让第二个参数与Lambda的入参结构强绑定,同时预留独立的配置参数位,既解决参数关联性问题,又满足后续扩展需求。
基础通用函数实现
先定义基础的通用函数,适配Lambda+结构化参数的调用模式:
// 定义接收结构化参数的异步处理器类型 type AsyncHandler<TParams extends object, TResult> = (params: TParams) => Promise<TResult>; function execute<TParams extends object, TResult>( handler: AsyncHandler<TParams, TResult>, params: TParams, config?: { // 这里可以添加任意扩展配置,比如超时、请求标识等 timeout?: number; requestId?: string; } ): Promise<TResult> { // 统一处理配置逻辑(比如超时包装、请求日志) const wrappedHandler = async () => { const controller = new AbortController(); const timeoutId = config?.timeout && setTimeout(() => controller.abort(), config.timeout); try { return await handler(params); } finally { clearTimeout(timeoutId); } }; return wrappedHandler(); } // 使用示例 const getPosts = async (params: { category: string; page: number }) => { const res = await fetch(`/api/posts?category=${params.category}&page=${params.page}`); return res.json(); }; // 调用时参数类型完全匹配,IDE自动提示 execute(getPosts, { category: "tech", page: 1 }, { timeout: 5000 });
扩展到React自定义请求钩子
基于上述思路,封装符合需求的React网络请求钩子,统一管理请求状态:
import { useState, useEffect, useCallback } from 'react'; // 定义请求配置项 type RequestHookConfig = { enabled?: boolean; // 是否自动触发初始请求 onSuccess?: (data: any) => void; onError?: (error: Error) => void; }; function useRequest<TParams extends object, TResult>( requestFn: (params: TParams) => Promise<TResult>, initialParams: TParams, config?: RequestHookConfig ) { const [data, setData] = useState<TResult | null>(null); const [loading, setLoading] = useState(false); const [error, setError] = useState<Error | null>(null); const fetchData = useCallback(async (params: TParams) => { setLoading(true); setError(null); try { const result = await requestFn(params); setData(result); config?.onSuccess?.(result); } catch (err) { const errorObj = err as Error; setError(errorObj); config?.onError?.(errorObj); } finally { setLoading(false); } }, [requestFn, config]); // 自动触发初始请求(可通过enabled配置关闭) useEffect(() => { if (config?.enabled !== false) { fetchData(initialParams); } }, [initialParams, fetchData, config?.enabled]); return { data, loading, error, refetch: fetchData // 手动触发请求的方法 }; } // 钩子使用示例 const fetchUser = async (params: { userId: number; includeProfile: boolean }) => { const res = await fetch(`/api/users/${params.userId}?includeProfile=${params.includeProfile}`); if (!res.ok) throw new Error('Failed to fetch user'); return res.json(); }; function UserPage() { const { data, loading, error, refetch } = useRequest( fetchUser, { userId: 456, includeProfile: true }, { enabled: true, onSuccess: (user) => console.log('User loaded:', user), onError: (err) => console.error('Fetch error:', err) } ); if (loading) return <div>Loading user data...</div>; if (error) return <div>Error: {error.message}</div>; return ( <div> <h2>{data?.username}</h2> <button onClick={() => refetch({ userId: 456, includeProfile: false })}>Hide Profile</button> </div> ); }
方案优势
- 参数强关联:通过泛型约束,结构化参数与Lambda入参类型完全匹配,IDE能提供精准的类型提示,避免参数错误
- 可扩展性强:独立的
config参数位可以自由添加超时控制、请求拦截、回调函数等扩展逻辑,不影响核心调用方式 - 状态统一管理:React钩子版本封装了加载、错误、数据状态,无需在组件中重复编写状态逻辑
内容的提问来源于stack exchange,提问作者tscheppe
相关产品推荐
相关产品推荐

