TypeScript:如何让Reducer工厂优先依据返回值进行类型推断?
如何让TypeScript优先根据Reducer返回值推断类型?
问题背景
我有一个Reducer工厂函数,其返回值类型依赖于Reducer的返回值。最初的类型定义可以正确推断类型:
type SomeValue<T> = { value: T }; const fabric: <T extends () => any>(reducer: T) => SomeValue<ReturnType<T>> = (reducer) => { return { value: reducer() }; }; // 正确推断为 SomeValue<number> const value1 = fabric(() => 1);
但当我修改Reducer,让它接收上一次的值时,类型推断出现问题。新的类型定义如下:
const fabric: <T>(reducer: (prev: undefined | T) => T) => SomeValue<T> = (reducer) => { let current: T | undefined = undefined; current = reducer(current); return { value: current }; };
显式指定参数类型时能正常工作:
// 正确推断为 SomeValue<number> const value2 = fabric((prevValue: number = 1) => prevValue + 1);
但省略参数类型时,类型推断失效,结果变成SomeValue<unknown>:
// 错误推断为 SomeValue<unknown>,期望是 SomeValue<number> const value3 = fabric((prevState = 1) => prevState);
解决方案
问题的根源是TypeScript的类型推断顺序:当参数类型定义为undefined | T时,TypeScript会优先从参数位置推断T,而无显式类型的参数只能推断为unknown。我们可以通过以下两种方式调整推断逻辑:
方案1:将参数改为可选类型(推荐)
把Reducer的参数定义为可选参数(prev?: T),它等价于prev: T | undefined,但TypeScript会结合参数的默认值优先推断T的类型:
type SomeValue<T> = { value: T }; const fabric: <T>(reducer: (prev?: T) => T) => SomeValue<T> = (reducer) => { let current: T | undefined = undefined; current = reducer(current); return { value: current }; }; // 正确推断为 SomeValue<number> const value = fabric((prevState = 1) => prevState);
方案2:通过泛型约束绑定返回值与参数类型
使用泛型约束,让Reducer的返回值类型同时作为参数的类型之一,强制TypeScript优先从返回值推断类型:
type SomeValue<T> = { value: T }; const fabric = <R extends (prev: ReturnType<R> | undefined) => ReturnType<R>>( reducer: R ): SomeValue<ReturnType<R>> => { let current: ReturnType<R> | undefined = undefined; current = reducer(current); return { value: current }; }; // 正确推断为 SomeValue<number> const value = fabric((prevState = 1) => prevState);
原理说明
- 方案1利用了TypeScript对可选参数的推断逻辑:当可选参数有默认值时,TypeScript会将默认值的类型作为泛型
T的候选类型,结合返回值的类型最终确定T。 - 方案2通过泛型约束
R extends (prev: ReturnType<R> | undefined) => ReturnType<R>,强制Reducer的参数类型必须是其返回值类型或undefined,从而让TypeScript优先从返回值推断ReturnType<R>,再反向约束参数类型。
内容的提问来源于stack exchange,提问作者BANO notIT
相关产品推荐
相关产品推荐

