我想知道是否有一种替代方法来指定不使用any
的函数类型“any function”(从而提高类型安全性)。为了澄清,我正在寻找以下类型的替代方法:
type AnyFunctionAsUsual = (...args: any[]) => any;
我可以将返回值替换为unknown
,但在下面的定义中仍然存在any
:
type AnyFunctionReturningUnknown = (...args: any[]) => unknown;
据我所知,类型AnyFunctionAsUsual
和AnyFunctionReturningUnknown
可以取相同的值,而且我还认为后者是足够类型安全的(因为就我而言,参数的any
没有禁用任何类型检查)。
但是eslint
不喜欢它,因为它仍然违反了no-explicit-any
规则,该规则包含在plugin:@typescript-eslint/recommended
中。
有没有一种方法可以定义一个类型,它可以和上面的两个类型具有相同的值,并且还可以使linter满意?(禁用linter或规则并不等同于使linter满意。)
1条答案
按热度按时间s5a0g9ez1#
你想让
SomeFunction
成为top type的函数,如果你有一个f
的函数,你可以把它赋给SomeFunction
类型的变量,如果你有一个x
的非函数,那么你 * 不能 * 把它赋给SomeFunction
。unknown
类型的函数排序。(你不能使用unknown
,因为它接受非函数。)你的
(...args: any) => unknown
或(...args: any[]) => unknown
类型满足这些条件,但是它们不是类型安全的,因为它们使用了不安全的any
“类型”。在安全类型系统中,有一个权衡,顶级类型的值容易 * 提供 *,但很难 * 消费 *。如果我想要unknown
类型的值,你可以给予我任何你想要的。但是一旦我有了它,如果不进一步检查它,我不知道该怎么做。如果我想要一个SomeFunction
类型的值,你可以给予我任何你想要的 function。所以一旦我有了它,我就可以做任何对 arbitrary 函数有效的事情,比如检查它的length
属性或者......嗯......我不能用它做很多事情。我不能调用它,因为我不知道它会接受什么参数。所以使用SomeFunction
将是困难的,或者至少是棘手的。(...args: any) => unknown
类型允许你调用它 * 无论你想要什么 *,即使这会立即导致运行时错误:这就是为什么不应该在这里使用
any
的原因。假设您想要一个
SomeFunction
的 * 安全 * 版本,那么我们应该确保参数列表没有被赋予“anything-goes”类型。它应该是相反的,你应该完全不能调用它,那是因为函数类型在它们的参数类型中是逆变的(更多信息请参见Difference between Variance, Covariance, Contravariance and Bivariance in TypeScript和--strictFunctionTypes
编译器选项的描述)。在TypeScript中,这意味着顶级函数类型的参数列表应该为bottom type。底部类型为never
类型:(...args: never) => unknown
充当函数顶级类型的能力主要在microsoft/TypeScript#35438中实现,并在microsoft/TypeScript#52387中完成,microsoft/TypeScript#52387将随TypeScript 5.0发布。在此之前,可以无错误地调用上面的f()
(即使它不安全),但其他调用将被拒绝。Playground代码链接