我在搜索"泛型参数推断未知"时发现了一些帖子和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个?

推荐答案

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

当您调用createFun(f => f(1));时,回调参数f => f(1)context-sensitivef的类型必须从函数的arg参数的类型推断为contextually.但是createFun是一个generic函数,它有一个类型参数T,其类型必须从回调参数的类型推断出来.因此,回调参数的类型取决于函数参数的类型,而函数参数的类型取决于回调参数的类型.这种依赖关系的循环经常导致推理失败,其中编译器将对一部分的推断推迟到它推断另一部分之后,在这一点上信息丢失并且事情回落到unknownany.

对于一个参数的pieces个依赖于参数的其他部分的情况,在TypeScrip中已经有了渐进式的改进,比如依赖于其他对象属性的对象属性,就像在microsoft/TypeScript#48538中实现的那样,但到目前为止,当单个上下文敏感函数的输入类型直接依赖于它自己时,还没有什么改进.我不知道这是否会得到支持;人们可能会在Microsoft/TypeScrip#47599中添加 comments ,或者提交新的问题.但我怀疑,它在任何人的优先级列表中都不是很高,特别是因为解决方法非常简单:只需手动指定类型参数:

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

请注意,从技术上讲,TypeScrip的推理算法可以完全重写为使用所谓的full 100 algorithm,如microsoft/TypeScript#30134中所讨论的.有些函数式编程语言是完全统一的,可以证明它们"正确"地推断类型.

不过,TypeScrip不太可能做到这一点.首先,更换推理算法将是一项巨大的努力.即使他们做出了这样的努力,也可能会让开发人员的体验变得更糟:参见this comment on microsoft/TypeScript#17520:

[TypeScrip的推理算法]不同于一些函数式编程语言实现的基于统一的类型推理,但它具有明显的优势,即能够在不完整的代码中进行部分推理,这对IDE中的语句完成非常有利.

Playground link to code

Typescript相关问答推荐

类型脚本类型字段组合

更新为Angular 17后的可选链运算符&?&问题

Angular 错误NG0303在Angular 项目中使用app.Component.html中的NGFor

部分类型化非 struct 化对象参数

TypeScrip:逐个 case Select 退出noUncheck kedIndexedAccess

类型脚本满足将布尔类型转换为文字.这正常吗?

是否可以从函数类型中创建简化的类型,go 掉参数中任何看起来像回调的内容,而保留其余的内容?

类型TTextKey不能用于索引类型 ;TOption

vue-tsc失败,错误引用项目可能无法禁用vue项目上的emit

为什么Typescript只在调用方提供显式泛型类型参数时推断此函数的返回类型?

TYPE FOR ARRAY,其中每个泛型元素是单独的键类型对,然后在该数组上循环

如何创建由空格连接的多个字符串的类型

Typescript -返回接口中函数的类型

抽象类对派生类强制不同的构造函数签名

使用Type脚本更新对象属性

Typescript将键数组映射到属性数组

map 未显示控制台未显示任何错误@reaction-google-map/api

类型';只读<;部分<;字符串|记录<;字符串、字符串|未定义&>';上不存在TS 2339错误属性.属性&q;x&q;不存在字符串

如何在没有空接口的情况下实现求和类型功能?

如何让 Promise 将它调用的重载函数的类型转发给它自己的调用者?