web-dev-qa-db-ja.com

TypeScriptタイプのbivarianceHackの目的は何ですか?

ReactのTypeScript型を読んでいるときに、bivarianceHack()関数宣言を含むこのパターンの使用例をいくつか見ました。

@ types/react/index.d.ts

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

他のインスタンス が使用されているので、React固有のパターンではないようですが、この特定のパターンが使用された理由に関するドキュメントは見つかりませんでした。

(event: E) => voidではなく、なぜこのパターンが使用されているのですか?

16
zzzzBov

これは、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 

遊び場リンク