使用 '--strictFunctionTypes' 在 Typescript 中有什么好处?

14

据我理解,Typescript中的--strictFunctionTypes编译选项会阻止一种非常常见的多态用法:

type Handler = (request: Request) => Response

const myHandler: Handler = (request: Request & { extraArg: boolean }) => {
  return !!request.extraArg
}

一般来说,我认为strict系列中的所有编译器选项都有很大的好处,但在这种情况下,我看到的只是它阻止了一个非常符合逻辑的行为。

那么,在哪些情况下此选项实际上会给出一些好处? 它又可以防止哪些有害的场景发生呢?


无论其类型级别效果如何,我建议打开此选项仅为了提高类型检查速度的好处,如此处所述:https://github.com/microsoft/TypeScript/wiki/Performance#using-faster-variance-checks。 - trias
2个回答

26

没有启用 strictFunctionTypes,实际上很容易导致运行时错误。

让我们考虑以下示例:

type Handler = (request: Request) => Response

const myHandler: Handler = (request: Request & { extraArg: string }) => {
    // extraArg is required so need to check for null
    request.extraArg.toUpperCase();
    return null as any;
}

declare let r: Request; // comes from sowhere 
myHandler(r); // no need to pass in the extraArg not required by the signature
因此,在上面的例子中,函数签名要求一个Request,所以我们只需要传递一个Request。但是实现期望接收到Request& { extraArg: string },其中extraArg是必需的,并且可以在没有进行检查的情况下访问它(毕竟如果需要调用方应该已经将其传递进去)。
这就是strictFunctionTypes可以防止的错误类型。如果签名中的参数是基础类型,而实现期望的是派生类型,则无法保证实现将接收到派生类型,因为签名仅要求传递基础类型。

5

这个选项解决了 TypeScript 编译器的一个错误,我的观点是如此。如果它不是一个错误,那么它只是一个糟糕的设计决策,而出现一个新的编译器选项证明了我的观点。让我们以一个例子开始,按默认设置,下面的代码将被编译而没有问题:

// Focus all your attention on callback signature
// It has date parameter which is a union type
function getCurrentYear(callback: (date: string | number) => void) {
   callback((Math.random() > 0.5) ? '2020' : 2020);
}

// note that we ignored the fact that in 50% cases our callback returns string type instead of number.
getCurrentYear((date: string) => {
    console.log(date.charAt(0)); // in 50% it is RUNTIME ERROR
});

因此,传递给getCurrentYear的箭头函数缩小了“date”参数的类型范围,TypeScript对此并不在意。 然而,在不同上下文中使用变量的相同技巧,即使没有任何严格规则,也会产生错误:

let x: string | number = (Math.random() > 0.5) ? '2020' : 2020;
const y: number = x; // COMPILE TIME ERROR

这样做更有意义,启用 --strictFunctionTypes 将要求编译器在回调函数中遵循相同的行为。这绝对会帮助你在大型项目中防止一些错误。

来源:

https://medium.com/javascript-in-plain-english/what-are-these-strict-compiler-options-in-typescript-part-2-a7e974b13e54


我对这里的示例代码感到困惑,因为 getCurrentYear 实际上并没有使用回调函数。在我看来,这似乎不是您演示的目的。 - g.delgado
@g.delgado 您是对的。有一个打字错误。已更新代码。 - Kirill Reznikov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接