TypeScript:如何让calculation匹配generator的泛型参数类型?
问题:如何让
calculation类型匹配generator的参数类型? 存在一个需传入另一函数并在其中调用的工厂函数,该函数的参数要么基于泛型类型,要么无需传入。请说明如何正确定义「calculation」,使其类型与「generator」的参数类型匹配?
原代码示例:
type Model = {id: number}; type Calc = Record<string, number>; declare function calc(record: Model): Calc; type OptFnArg<Param, Result> = Param extends void ? () => Result : (arg: Param) => Result; const run = function <Param>(modelFactory: OptFnArg<Param, Model>) { const calculation = (param: Param) => calc(modelFactory(param)); //^ 如何让`calculation`能被`generator`接受? // 类型'(param: Param) => Calc'无法赋值给类型'OptFnArg<Param, Calc>'。 const result = generator<Param>(calculation); return result; } declare function generator<Param>(calculation: OptFnArg<Param, Calc>): '🎲' // 合法调用示例: run<void>(() => ({id: 1})); // @ts-expect-error run<void>((q) => ({id: 1})); run<number>((id: number) => ({id})); // @ts-expect-error run<string>((id: number) => ({id}));
问题根源
当Param为void时,OptFnArg<Param, Calc>对应的是无参函数() => Calc,但你定义的calculation是接受void类型参数的函数(param: void) => Calc——这两个类型在TypeScript中不兼容:无参函数不允许传入任何参数,而接受void参数的函数可以传入undefined或空值,因此类型校验失败。
解决方案
通过泛型条件分支构造完全符合OptFnArg<Param, Calc>类型的calculation函数:
const run = function <Param>(modelFactory: OptFnArg<Param, Model>) { // 根据Param的类型构造匹配的calculation函数 const calculation = (Param extends void ? () => calc(modelFactory()) : (param: Param) => calc(modelFactory(param)) ) as OptFnArg<Param, Calc>; const result = generator<Param>(calculation); return result; }
原理说明
- 当
Param为void时,创建无参函数() => calc(modelFactory()),完全匹配OptFnArg<void, Calc>的要求; - 当
Param为其他类型时,创建对应参数类型的函数(param: Param) => calc(modelFactory(param)),匹配OptFnArg<Param, Calc>的定义; - 类型断言
as OptFnArg<Param, Calc>帮助TypeScript正确推断泛型分支后的函数类型,避免编译器报错。
修改后,calculation可完美适配generator的参数类型,同时保留原有的合法调用校验逻辑。
内容的提问来源于stack exchange,提问作者c01nd01r
相关产品推荐
相关产品推荐

