Historie der Frage
Standardmäßig erlaubt TypeScript eine gewisse "Schludrigkeit" bei der Zuordnung von Typensignaturen von Funktionen, indem es zulässt, dass konforme und nicht konforme Funktionen als kompatibel betrachtet werden. Mit TypeScript 2.6 wurde die Option strictFunctionTypes eingeführt, die eine strenge Typüberprüfung von Funktionen garantiert und eine Vielzahl von Fehlerklassen verhindert, insbesondere in großen Codebasen.
Problem
Ohne strenge Überprüfung kann es vorkommen, dass eine Handler- oder Callback-Funktion einen größeren oder spezifischeren Typ von Parametern akzeptiert, und dies bleibt für den Entwickler unbemerkt. Dies führt zu Laufzeitfehlern im Zusammenhang mit der Kovariante von Rückgabewerten und der Kontravarianz von Argumenten.
Lösung
Die Option strictFunctionTypes führt eine strenge Kontravarianz für die Typen der Funktionsparameter ein. Jetzt sind Funktionen nur dann kompatibel, wenn der Typ des Quellparameters ein Supertyp des Zielparameters ist und nicht umgekehrt.
Beispielcode:
type Animal = { name: string }; type Cat = { name: string; meow: () => void }; let animalHandler: (a: Animal) => void; let catHandler: (c: Cat) => void; animalHandler = catHandler; // Fehler bei strictFunctionTypes: Argument ist zu spezifisch catHandler = animalHandler; // Erlaubt, Cat ist ein Subtyp von Animal
Wesentliche Merkmale:
War es früher möglich, einen Handler mit einem spezifischeren Typ von Parameter zuzuweisen, bevor strictFunctionTypes eingeführt wurde?
Ja, vor der Aktivierung von strictFunctionTypes erlaubte TypeScript die Zuweisung spezifischerer Funktionen an allgemeinere, was zu Laufzeitproblemen führte:
enum E { A, B } const f: (e: E) => void = (e: E.A) => {} // Ohne strictFunctionTypes: erlaubt
Wie beeinflusst strictFunctionTypes Callbacks mit optionalen Parametern?
Wenn Parameter der Callback-Funktion einige Parameter optional machen, verhindert die strenge Überprüfung die Verwendung einer Funktion mit weniger obligatorischen Parametern an einer Stelle, wo eine Funktion mit mehr erwartet wird. Dies verhindert, dass der Callback nicht die benötigten Daten erhält.
Wird es Kompatibilitätsprobleme bei der Aktivierung von strictFunctionTypes in alten Projekten geben?
Ja, es besteht das Risiko, dass neue Kompilierungsfehler auftreten, da viele Funktionen und Handler möglicherweise einander mit Verletzung der Kontravarianz zugewiesen wurden. Dies tritt häufig bei Rückrufen oder bei der Verwendung von APIs von Drittanbieter-Bibliotheken ohne strikte Typisierung auf.
In einem großen Projekt akzeptieren Ereignis-Handler spezifischere Typen (MouseEvent statt des allgemeinen Event). Dies wird erst bei Aktivierung der strengen Option erkannt, was zu Fehlern beim Start mit verschiedenen Ereignisquellen führt.
Vorteile:
Nachteile:
Das Projekt verwendet seit Beginn strictFunctionTypes. Bei der Hinzufügung neuer Handler werden alle Unterschiede zwischen den Typen automatisch vom Compiler erkannt. Der Code wird stabiler gegenüber Tippfehlern und ist einfacher zu warten.
Vorteile:
Nachteile: