typescript - 推断通用参数未知

标签 typescript typescript-generics

我在搜索“推断未知的通用参数”时发现了一些帖子和 github 问题,但我的技能水平似乎不足以让我理解这个问题。

这是我的代码(playground):

function createFun<T>(arg: (f: (id: T) => T) => T) {
  // body of this doesn't matter
}

const fun1 = createFun((f) => f(1)); // T is inferred to be unknown
const fun2 = createFun((f) => f("")); // T is inferred to be unknown
const fun3 = createFun((f) => f(true)); // T is inferred to be unknown

// Question:

// can createFun be modified such that the above is inferred as

//   * createFun<number>((f) => f(1));
//   * createFun<string>((f) => f(""));
//   * createFun<boolean>((f) => f(true));

// ?

是否可以修改createFun,以便正确推断通用参数T

我想知道,因为

createFun<string>((f) => f(1));

时引发错误(理应如此)
createFun<number>((f) => f(1));

不(应该)。

那么 Typescript 显然有足够的信息来正确推断 T 吗?

最佳答案

这是目前 TypeScript 的设计限制,请参阅 microsoft/TypeScript#47599 .

当您调用createFun(f => f(1));时,回调参数f => f(1) 上下文敏感f的类型必须推断contextually来自 arg 的类型函数的参数。但是createFungeneric函数,带有类型参数 T其类型必须从回调参数的类型推断。因此,回调参数的类型取决于函数参数的类型,而函数参数的类型又取决于回调参数的类型。这种依赖关系的循环性通常会导致推理失败,编译器会将一个片段的推理推迟到推理另一片段之后,此时信息就会丢失,事情会回退到 unknown。或any .

TypeScript 进行了渐进式改进,以处理参数的部分依赖于参数的其他部分的情况,例如依赖于其他对象属性的对象属性,如 microsoft/TypeScript#48538 中实现的,但到目前为止,当单个上下文相关函数的输入类型直接依赖于其自身时,什么也没有。我不知道这是否会得到支持;人们可能会向 microsoft/TypeScript#47599 添加评论或提交新问题。但我怀疑它在任何人的优先级列表中都不高,特别是因为解决方法非常简单:只需手动指定类型参数:

const fun1 = createFun<number>((f) => f(1)); // easiest

或者以多种方式解开这个结:

type IdFunc<T> = (id: T) => T;    
function createFun<T>(arg: (f: IdFunc<T>) => T) {}


const fun2 = createFun((f: IdFunc<string>) => f("")); // harder 
const fun3 = createFun<boolean>((f: IdFunc<boolean>): boolean => f(true)); // extreme

请注意,从技术上来说,TypeScript 的推理算法可以完全重写以使用所谓的full unification算法,如 microsoft/TypeScript#30134 中讨论的。一些函数式编程语言具有完全的统一性,并且可以证明它们“正确”地推断类型。

不过,TypeScript 不太可能做到这一点。首先,更换推理算法需要付出巨大的努力。即使他们付出了这样的努力,也可能会让开发者体验变得更糟:请参阅this comment on microsoft/TypeScript#17520 :

[TypeScript's inference algorithm] differs from the unification based type inference implemented by some functional programming languages, but it has the distinct advantage of being able to make partial inferences in incomplete code which is hugely beneficial to statement completion in IDEs.

Playground link to code

关于typescript - 推断通用参数未知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76640759/

相关文章:

typescript - 如何让 TS 在通用构建器函数中推断回调?

javascript - map、filter 与 for 和 forEach 之间的区别以及使用 map 和 filter 优于 For 和 forEach 循环的优势是什么?

angularjs - 扩展 Angular CLI 任务

typescript - 默认泛型作为参数按预期工作,但不作为函数参数的返回类型

typescript - 在 TypeScript 中,当类型是函数的参数时,有没有办法限制 Partial<T> 类型的额外/多余属性?

typescript - 为对象的键添加前缀仅考虑重叠

javascript - Angular 2如何将对象数组放入另一个对象数组

dependency-injection - 带有可选参数的 DI 构造函数

TypeScript 属性装饰器 : access to other properties

typescript - 键在应该用于索引类型时却不能使用