Это связано с совместимостью функций в опции 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
Тем не менее, существует оговорка к строгому типу функции, указанному в PR
Более строгая проверка применяется ко всем типам функций, за исключением тех, которые исходят из объявлений метода или конструктора .Методы исключены специально, чтобы гарантировать, что универсальные классы и интерфейсы (такие как Array) по-прежнему в основном связаны ковариантно.Результатом строгой проверки методов будет гораздо большее критическое изменение, поскольку большое количество универсальных типов станет инвариантным (даже в этом случае мы можем продолжить изучение этого более строгого режима).
Акцентдобавлено
Таким образом, роль хака состоит в том, чтобы разрешить бивариантное поведение EventHandler
даже при strictFunctionTypes
.Поскольку подпись обработчика события будет иметь свой источник в объявлении метода, она не будет подвергаться более строгим проверкам функций.
type BivariantEventHandler<E extends Animal> = { bivarianceHack(event: E): void }["bivarianceHack"];
let o2: BivariantEventHandler<Animal> = (o: Dog) => { } // still ok under strictFunctionTyes
Playground link