TypeScript中NoInfer类型未按预期工作的问题咨询
TypeScript类型推断失败原因分析
问题代码
以下代码中,编译器无法正确推断泛型T的类型,导致state和inferred都被标记为unknown:
function inferTest<T>(factory: (setter: (setterFn: (arg: NoInfer<T>) => NoInfer<T>) => void) => T) { return factory(null!); } const inferred = inferTest((setter) => ({ count: 0, increment: () => setter(state => ({ count: state.count + 1 })) // 'state' is of type 'unknown'. })); console.log(inferred.count); // 'inferred' is of type 'unknown'.
期望与实际结果
期望T被推断为:
{ count: number, increment: () => void, }
但实际编译器将T设为unknown,触发两个编译错误:
'state' is of type 'unknown'. 'inferred' is of type 'unknown'.
移除increment属性后,代码可正常工作,T被正确推断为{count: number}:
function inferTest<T>(factory: (setter: (setterFn: (arg: NoInfer<T>) => NoInfer<T>) => void) => T) { return factory(null!); } const inferred = inferTest(() => ({ count: 0 })); console.log(inferred.count);
原因解析
核心问题在于类型推断的循环依赖:
- 泛型
T的类型本应从factory函数的返回值推断而来,也就是你定义的包含count和increment的对象。 - 但
increment的实现中调用了setter,而setter接收的setterFn参数要求输入NoInfer<T>类型的state——这里的NoInfer<T>只是告诉编译器“不要从这个位置反向推断T”,但并没有解决T本身的定义依赖于increment内部对T的引用。 - 此时形成了闭环:
T的完整类型需要increment的类型,而increment的类型又需要知道T是什么才能确定state的类型。TypeScript无法解开这个循环,只能将T默认设为unknown。
当移除increment后,factory的返回值是明确的{count: number},没有依赖T的其他部分,编译器可以直接推断出T的类型,自然不会出现错误。
内容的提问来源于stack exchange,提问作者ChapterSevenSeeds
相关产品推荐
相关产品推荐

