如何根据外层函数入参决定内层函数对应参数是否可选
解决方案
1. 基础场景的更简洁实现(替代函数重载)
除了手动写多个函数重载,你可以用泛型条件类型实现相同效果,代码更精简,也便于后续扩展:
// 泛型T接收外层参数a的类型 function outer<T extends number | undefined>(a: T): // 条件判断:如果a是number类型,返回的内层函数b可选,否则必填 T extends number ? (b?: number) => void : (b: number) => void { return function inner(b?: number) { // 业务逻辑 } as any } // 调用校验 outer(1)(2); // 合法 outer(1)(); // 合法 outer()(1); // 合法 outer()(); // 类型报错,符合预期
2. Redux Toolkit场景报错修复
你之前的代码报错的核心原因是:createAsyncThunk默认生成的AsyncThunk实例入参类型是和你传入的payload creator参数匹配的(你写的是recipeId?: string[],所以默认返回的thunk入参是可选类型),TS无法自动将这个默认类型和你两个重载声明的不同返回类型做兼容匹配,只需要给返回值加上显式的联合类型断言即可,修复后的完整代码如下:
import { AsyncThunk, createAsyncThunk } from "@reduxjs/toolkit"; type RecipeGetter = () => string[]; type ThunkWithOptionalRecipeIds = AsyncThunk< Record<string, string>, string[] | undefined, Record<string, never> >; type ThunkWithRequiredRecipeIds = AsyncThunk< Record<string, string>, string[], Record<string, never> >; // 注意:TS重载需要把更精确的签名放在前面 function getFetchRecipesByIdThunk( typePrefix: string, recipeIdGetter: RecipeGetter, ): ThunkWithOptionalRecipeIds; function getFetchRecipesByIdThunk( typePrefix: string, recipeIdGetter?: RecipeGetter, ): ThunkWithRequiredRecipeIds; function getFetchRecipesByIdThunk( typePrefix: string, recipeIdGetter?: RecipeGetter, ) { // 此处添加显式类型断言,告诉TS返回值匹配两个重载的联合类型 return createAsyncThunk(typePrefix, async (recipeId?: string[]) => { // 业务逻辑示例:优先用传入的id,没有就用getter获取 const targetIds = recipeId ?? recipeIdGetter?.(); if (!targetIds) throw new Error("缺少recipeId参数"); // 接口请求等逻辑 return {}; }) as ThunkWithOptionalRecipeIds | ThunkWithRequiredRecipeIds; } // 调用校验 getFetchRecipesByIdThunk('test/fetch', () => ['1','2'])(); // 合法,无需传参 getFetchRecipesByIdThunk('test/fetch')(['1','2']); // 合法,必须传参 getFetchRecipesByIdThunk('test/fetch')(); // 类型报错,符合预期
内容的提问来源于stack exchange,提问作者Pavel
相关产品推荐
相关产品推荐

