TypeScript中一个鲜为人知的内置接口是VoidFunction
,它应该表示任何不带参数并返回void的函数。一个更不为人所知的是NewableFunction
,其听起来像,它应该表示任何"是"的函数;"可再生";或";可施工的";(可能使用类似(new (...) => ...
)的构造签名,但当您尝试使用此接口时,会出现意外行为。
例如,请尝试使用参数。使用Parameters<VoidFunction>
,您可以获得预期的[]
:
// Makes sense
type VoidParams1 = Parameters<VoidFunction>;
// ^? []
使用ConstructorParameters
会产生错误,因为VoidFunction
是不可构造的。然而,Parameters
和ConstructorParameters
都不接受NewableFunction
:
//@ts-expect-error Is newable, not a regular function
type CtorParams1 = Parameters<NewableFunction>;
// What?
type CtorParams2 = ConstructorParameters<NewableFunction>;
// Error: ^^^^^^^^^^^^^^^
// Type 'NewableFunction' does not satisfy the constraint 'abstract new (...args: any) => any'.
这已经足够奇怪了,但当你把它用作代码类型时:
function newfn(f: NewableFunction) {}
// This line is OK
newfn(class {});
// Error on the following line
newfn(Date); // `new Date()`...?
// ^^^^
// Argument of type 'DateConstructor' is not assignable to parameter of type 'NewableFunction'.
// Types of property 'apply' are incompatible.
// ...
// Type 'new () => any' is not assignable to type '(this: any) => any'.
那么,如果我不能将NewableFunction
用作可更新函数,它有什么意义呢?为什么像new (...args) => any
这样的类型还没有内置呢?它很常见。问题ms/TS#44337似乎没有解决这些问题。。。
游乐场
它似乎只接受";严格可更新";函数-只能用new
调用的函数?使用newfn(Date)
会引发错误,但newfn(Float32Array)
不会。但是,为什么要这样设计呢?为什么这有用?
哦,我不知道我怎么错过了这个,但在3.2版本的发行说明中,我们得到了strictBindCallApply
,它部分由两个新接口CallableFunction
和NewableFunction
实现。VoidFunction
与此无关。
function foo(a: number, b: string): string {
return a + b;
}
let a = foo.apply(undefined, [10]); // error: too few argumnts
let b = foo.apply(undefined, [10, 20]); // error: 2nd argument is a number
let c = foo.apply(undefined, [10, "hello", 30]); // error: too many arguments
let d = foo.apply(undefined, [10, "hello"]); // okay! returns a string
以下是他们对这些新接口的看法:
这是通过在
lib.d.ts
中引入两种新类型CallableFunction
和NewableFunction
来实现的。这些类型分别包含正则函数和构造函数的bind
、call
和apply
的专用泛型方法声明。声明使用通用的rest参数(参见#24897)以强类型的方式捕获和反映参数列表。在strictBindCallApply
模式中,使用这些声明来代替Function类型提供的(非常宽松的)声明。
所以它们实际上并不是我们TypeScript的常规用户要使用的。。。