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

TypeScript中链式可选函数的参数类型推断问题

解决Slice函数中ctx类型自动推断问题

问题分析

你的代码中,泛型约束存在循环依赖:在定义T的约束时,返回值里的ctx.api类型直接引用了未完成推断的T,导致TypeScript无法解析ctx的具体类型,最终将其推断为any。

解决方案

通过拆分类型定义,利用TypeScript对循环条件类型的支持,让ctx.api的类型能从T中正确提取:

// 定义单个slice方法的类型:接受state和payload,返回新状态或带ctx的异步函数
type SliceFn<S, P, API> = (state: S, payload: P) => S | ((ctx: { api: API }) => Promise<void>);

// 从slice配置T中提取api类型:每个api方法对应原方法的payload参数
type SliceAPI<T, S> = {
  [K in keyof T]: T[K] extends SliceFn<S, infer P, any> 
    ? (payload: P) => void  // 若需要api方法包含state,改为 (state: S, payload: P) => void
    : never;
};

// 重构slice函数的泛型约束
export function slice<
  S extends Record<string, any>,
  T extends Record<keyof T, SliceFn<S, any, SliceAPI<T, S>>>
>(
  config: T,
  { initialState }: { initialState: S },
) {
  return {};
}

// 测试示例
interface TestState {
  isTest: boolean;
}

const s = slice({
  login: (state: TestState, param: number) => async (ctx) => {
    type T1 = typeof ctx.api; 
    // 现在类型为 { login: (payload: number) => void; }
    // 若修改SliceAPI为包含state,则类型为 { login: (state: TestState, payload: number) => void; }
  },
},
{ initialState: { isTest: true } });

说明

  1. SliceFn:明确单个slice方法的结构,将ctx.api的类型作为泛型参数传入,避免直接在约束中引用未推断的T。
  2. SliceAPI:通过条件类型从T中提取每个方法的payload类型,生成对应的api方法签名。
  3. 泛型约束调整:让T的每个方法都关联SliceAPI<T, S>,形成合法的循环依赖,TypeScript会自动完成类型推断。

内容的提问来源于stack exchange,提问作者Andy Jessop

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 03:10:35