TypeScript中createHandler如何根据入参返回对应类型的createState
问题原因
你遇到的类型推导异常来自两个核心原因:
- TypeScript默认不会自动将函数入参的子类型和返回值类型做绑定映射。你当前将
createHandler的入参定义为QueryKey | 生成函数的联合类型,TS无法根据实际传入的参数类型自动收窄返回值里createState的类型,只会将其识别为两种函数的联合类型,自然无法精准推导参数类型。 - 你返回的两个
createState匿名函数没有显式标注data参数的类型,TS无法做上下文类型推导时就会默认将其推导为any。
解决方案
你提到的函数重载是最直观、可读性最高的方案,实现代码如下:
前置类型定义(根据你的实际业务调整)
// 你的自定义QueryKey类型示例 type QueryKey = string; // 你的自定义State类型示例 type State = Record<string, any>; // 你的自定义TData类型示例 type TData = Record<string, any>; // 假设你已经有createState的实现 declare function createState(data: TData, queryKey: QueryKey): State;
函数重载实现
// 重载1:传入QueryKey实例时,返回的createState仅接收data参数 export function createHandler(queryKey: QueryKey): { createState: (data: TData) => State } // 重载2:传入QueryKey生成函数时,返回的createState接收data和id两个参数 export function createHandler(queryKeyCreator: (idForQueryKey: string) => QueryKey): { createState: (data: TData, idForQueryKey: string) => State } // 兼容两种入参的实现签名 export function createHandler( createQueryKeyOrQueryKey: QueryKey | ((idForQueryKey: string) => QueryKey), ) { return { createState: typeof createQueryKeyOrQueryKey !== "function" ? (data: TData) => createState(data, createQueryKeyOrQueryKey) : (data: TData, id: string) => createState(data, createQueryKeyOrQueryKey(id)), }; }
效果验证
// 场景1:传入QueryKey实例 const queryKey = "some-query-key" const handler1 = createHandler(queryKey) handler1.createState({ a: 123 }) // ✅ 类型校验通过 handler1.createState({ a: 123 }, "some-id") // ❌ TS报错:参数数量不匹配 // 场景2:传入QueryKey生成函数 const queryKeyCreator = (id: string) => "some-query-key" + id const handler2 = createHandler(queryKeyCreator) handler2.createState({ a: 123 }) // ❌ TS报错:缺少第二个id参数 handler2.createState({ a: 123 }, "some-id") // ✅ 类型校验通过
泛型条件类型实现(可选)
如果你后续需要扩展更多类型逻辑,也可以用泛型条件类型替代重载,效果完全一致:
type CreateHandlerReturn<T extends QueryKey | ((id: string) => QueryKey)> = T extends QueryKey ? { createState: (data: TData) => State } : { createState: (data: TData, idForQueryKey: string) => State } export function createHandler<T extends QueryKey | ((id: string) => QueryKey)>( createQueryKeyOrQueryKey: T ): CreateHandlerReturn<T> { return { createState: typeof createQueryKeyOrQueryKey !== "function" ? (data: TData) => createState(data, createQueryKeyOrQueryKey) : (data: TData, id: string) => createState(data, createQueryKeyOrQueryKey(id)), } as CreateHandlerReturn<T> }
内容的提问来源于stack exchange,提问作者Bennett Dams
相关产品推荐
相关产品推荐

