在TypeScript类型中bivarianceHack的目的是什么?

zzz*_*Bov 11 types typescript

在阅读React的TypeScript类型时,我看到了涉及bivarianceHack()函数声明的这种模式的一些用法:

@类型/反应/ index.d.ts

type EventHandler<E extends SyntheticEvent<any>> = { bivarianceHack(event: E): void }["bivarianceHack"];
Run Code Online (Sandbox Code Playgroud)

搜索并没有让我得到任何关于为什么使用这种特定模式的文档,尽管我发现这个模式的其他实例在使用中,所以它似乎不是特定于React的模式.

为什么要使用这种模式而不是(event: E) => void

Tit*_*mir 20

这与strictfunctionTypes选项下的功能兼容性有关.在此选项下,如果参数是派生类型,则无法将其传递给将传入基类参数的函数.例如:

class Animal { private x:undefined }
class Dog extends Animal { private d: undefined }

type EventHandler<E extends Animal> = (event: E) => void

let o: EventHandler<Animal> = (o: Dog) => { } // fails under strictFunctionTyes
Run Code Online (Sandbox Code Playgroud)

然而,PR中有一个严格的功能类型的警告

更严格的检查适用于所有函数类型,但源自method或construcor声明的函数类型除外.特别排除方法以确保通用类和接口(例如Array)继续主要关联.严格检查方法的影响将是一个更大的突破性变化,因为大量的泛型类型将变得不变(即便如此,我们可能会继续探索这种更严格的模式).

强调补充说

因此,黑客的作用是允许EventHandler甚至在下的双变量行为strictFunctionTypes.由于事件处理程序的签名将在方法声明中具有它的源,因此它不会受到更严格的函数检查.

type BivariantEventHandler<E extends Animal> = { bivarianceHack(event: E): void }["bivarianceHack"];
let o2: BivariantEventHandler<Animal> = (o: Dog) => { } // still ok  under strictFunctionTyes 
Run Code Online (Sandbox Code Playgroud)

游乐场链接

  • 很酷,所以他们首先启用有争议的标志,然后他们使用黑客手段来避免遵循该标志规定的规则。 (13认同)