为什么 TypeScript 不能正确推断出“this”类型?

Edu*_*ato 7 typescript

取以下函数:

function test<T>(this: { value: T }) {
  return this.value;
}
Run Code Online (Sandbox Code Playgroud)

如果您使用call, applyorbind并提供this上下文,TypeScript 将不会推断提供的类型,并且unknown在这种情况下它将返回。

const a = test.apply({ value: 1 }); // a: unknown
const b = test.call({ value: 'b' }); // b: unknown
const fn = test.bind({ value: true }); // fn: () => unknown
Run Code Online (Sandbox Code Playgroud)

好的,这可能是因为apply,例如,被声明为apply<T, R>(this: (this: T) => R, thisArg: T): R,所以它需要您告知R返回类型。但如果你只显式声明函数的类型test,你将得到正确的类型:

const typed = (test<number>).apply({ value: 1 }); // typed: number
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况?为什么它没有推断,R但当我提供类型时它却推断出来了?

jca*_*alz 3

bind// callTypeScriptsupply 3.2 中引入的支持(在microsoft/TypeScript#27028中实现)无法真正正确处理重载泛型函数。根据文档,“在泛型函数上使用这些方法时,类型参数将被替换为[类型unknown]”(它表示空对象类型{},但自 TypeScript 3.5 以来一直如此unknown,如microsoft/TypeScript#30637中实现的那样)。这解释了您所看到的行为。microsoft/TypeScript#54707有一个开放的功能请求,要求改进此处的支持,但目前它还不是该语言的一部分。

至于为什么它与 一起工作(test<number>),这是一个实例化表达式,其中指定的类型参数被替换为泛型函数类型参数,而不调用该函数。所以test<number>不再是一个通用函数:

function test<T>(this: { value: T }) {
    return this.value;
}
type Test = typeof test // <T>(this: {value: T}) => T

const tn = test<number>;
type TestNumber = typeof tn // (this: { value: number; }) => number
Run Code Online (Sandbox Code Playgroud)

它只是特定的函数类型,(this: { value: number }) => number//bind应该按需要工作。callapply

Playground 代码链接