You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中createHandler如何根据入参返回对应类型的createState

问题原因

你遇到的类型推导异常来自两个核心原因:

  1. TypeScript默认不会自动将函数入参的子类型和返回值类型做绑定映射。你当前将createHandler的入参定义为QueryKey | 生成函数的联合类型,TS无法根据实际传入的参数类型自动收窄返回值里createState的类型,只会将其识别为两种函数的联合类型,自然无法精准推导参数类型。
  2. 你返回的两个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 23:54:05