Achtergrond
Standaard staat TypeScript enige "losheid" toe bij het afstemmen van type-signaturen van functies, waarbij omkeerbare en niet-omkeerbare functies als compatibel worden beschouwd. Met de komst van TypeScript 2.6 is de optie strictFunctionTypes geïntroduceerd, die een strikte typecontrole voor functies garandeert en veel klassen van fouten voorkomt, vooral in grote codebases.
Probleem
Zonder strikte controle kan het voorkomen dat een handler-functie of callback meer of specifieker typeparameters accepteert, wat onopgemerkt kan blijven voor de ontwikkelaar. Dit leidt tot runtime-fouten gerelateerd aan covariantie van geretourneerde types en contravariantie van argumenten.
Oplossing
De optie strictFunctionTypes introduceert strikte contravariantie voor de typeparameters van functies. Nu zijn functies alleen compatibel als de typeparameter van de bron een supertype van de doelparameter is, en niet andersom.
Voorbeeldcode:
type Animal = { name: string }; type Cat = { name: string; meow: () => void }; let animalHandler: (a: Animal) => void; let catHandler: (c: Cat) => void; animalHandler = catHandler; // Fout bij strictFunctionTypes: argument is te specifiek catHandler = animalHandler; // Toegestaan, Cat is subtype van Animal
Belangrijke kenmerken:
Kon je eerder een handler met een specifieker type parameter toewijzen, voordat strictFunctionTypes verscheen?
Ja, vóór het inschakelen van strictFunctionTypes stond TypeScript het toe om specifieker functies toe te wijzen in plaats van algemene, wat leidde tot runtime-problemen:
enum E { A, B } const f: (e: E) => void = (e: E.A) => {} // Zonder strictFunctionTypes: toegestaan
Hoe beïnvloedt strictFunctionTypes callbacks met optionele parameters?
Als de parameters van de callbackfunctie bepaalde parameters optioneel maken, laat strikte controle niet toe dat een functie met minder verplichte parameters wordt gebruikt op een plaats waar een functie met meer parameters wordt verwacht. Dit voorkomt situaties waarin de callback niet de benodigde gegevens ontvangt.
Zullen er compatibiliteitsproblemen zijn bij het inschakelen van strictFunctionTypes in oude projecten?
Ja, er is een risico op nieuwe compilatiefouten, omdat veel functies en handlers mogelijk aan elkaar zijn toegewezen met een schending van de contravariantie. Dit komt vaak voor bij callbacks of bij het gebruik van API's van externe bibliotheken zonder strikte typisering.
In een groot project accepteren event-handlers specifieker types (MouseEvent in plaats van algemeen Event). Dit wordt pas ontdekt bij het inschakelen van de strikte optie, wat leidt tot fouten bij runtime met verschillende eventbronnen.
Voordelen:
Nadelen:
Het project gebruikt strictFunctionTypes vanaf het begin. Bij het toevoegen van nieuwe handlers worden alle discrepanties tussen types automatisch ontdekt door de compiler. De code wordt robuuster tegen typefouten en is gemakkelijker te onderhouden.
Voordelen:
Nadelen: