Historia de la pregunta
Por defecto, TypeScript permite cierta "flexibilidad" al hacer coincidir las firmas de tipos de funciones, permitiendo que las funciones covariantes y contravariantes sean consideradas compatibles. A partir de TypeScript 2.6, se introdujo la opción strictFunctionTypes, que garantiza una verificación estricta de tipos de funciones y previene múltiples clases de errores, especialmente en grandes bases de código.
Problema
Sin verificación estricta, puede suceder que un manejador de función o callback acepte un tipo de parámetros más específico o adicional y esto pase desapercibido para el desarrollador. Esto lleva a errores en tiempo de ejecución relacionados con la covarianza de tipos de retorno y la contravarianza de argumentos.
Solución
La opción strictFunctionTypes introduce una contravarianza estricta para los tipos de parámetros de funciones. Ahora, las funciones son compatibles solo si el tipo de parámetro fuente es un supertipo del parámetro de destino, y no al revés.
Ejemplo de código:
type Animal = { name: string }; type Cat = { name: string; meow: () => void }; let animalHandler: (a: Animal) => void; let catHandler: (c: Cat) => void; animalHandler = catHandler; // Error con strictFunctionTypes: el argumento es demasiado específico catHandler = animalHandler; // Permitido, Cat es un subtipo de Animal
Características clave:
¿Se podría asignar un manejador con un tipo de parámetro más específico antes de la llegada de strictFunctionTypes?
Sí, antes de activar strictFunctionTypes, TypeScript permitía asignar funciones más específicas en lugar de generales, lo que llevaba a problemas en tiempo de ejecución:
enum E { A, B } const f: (e: E) => void = (e: E.A) => {} // Sin strictFunctionTypes: permitido
¿Cómo afecta strictFunctionTypes a los callbacks con parámetros opcionales?
Si los parámetros de la función de callback hacen que ciertos parámetros sean opcionales, la verificación estricta no permitirá usar una función con menos parámetros obligatorios en un lugar donde se espera una función con un mayor número. Esto previene situaciones en las que el callback no recibe los datos necesarios.
¿Habrá problemas de compatibilidad al activar strictFunctionTypes en proyectos antiguos?
Sí, existe el riesgo de que surjan nuevos errores de compilación, ya que muchas funciones y manejadores podrían haberse asignado entre sí violando la contravarianza. Esto se encuentra más comúnmente en callbacks o al utilizar APIs de bibliotecas de terceros sin una tipificación estricta.
En un gran proyecto, los manejadores de eventos aceptan tipos más específicos (MouseEvent en lugar del general Event). Esto no se detecta hasta que se activa la opción estricta, llevando a errores en tiempo de ejecución con diferentes fuentes de eventos.
Pros:
Contras:
El proyecto utiliza strictFunctionTypes desde el principio. Al agregar nuevos manejadores, todas las discrepancias entre los tipos son detectadas automáticamente por el compilador. El código se vuelve más resistente a errores tipográficos y es más fácil de mantener.
Pros:
Contras: