TypeScript 6.0 Strict Function Types: Why Contravariance Breaks Your Existing Callbacks TypeScript 6.0 enables strictFunctionTypes by default, enforcing contravariant parameter checking for function properties and breaking callbacks that relied on bivariant behavior. Developers must understand that a callback accepting a base type like Animal cannot safely be called with a derived type like Dog under strict checking. The distinction between method signatures and function properties determines variance behavior, and the solution is not to weaken types with any but to restructure callbacks using variance-aware patterns. This article was written with the assistance of AI, under human supervision and review. Most TypeScript migration failures stem from a single misunderstood compiler flag: strictFunctionTypes . The pattern that breaks production is deceptively simple—a callback that accepts a base type where the consumer expects a derived type. TypeScript 6.0 enables strict mode by default, which means codebases that never configured contravariance checking will fail to compile overnight. The failure mode here is subtle but expensive. A callback registered to an array method expects Animal , but the implementation passes Dog . Pre-6.0 TypeScript allowed this through bivariant parameter checking. Post-6.0, the compiler rejects it as unsafe. Teams scramble to fix hundreds of type errors without understanding the underlying variance rules, often choosing any or incorrect casts that introduce runtime bugs. The distinction between function properties and method signatures becomes critical—one enforces contravariance, the other permits bivariance for historical reasons. %% alt: Bivariant checking allows derived types where base types are expected The correct approach requires understanding contravariance: function parameters must accept types that are the same or less specific than what the function signature declares. When strictFunctionTypes activates, TypeScript enforces this rule for function properties but not method signatures. The solution is not to weaken types with any , but to restructure callbacks using proper variance-aware patterns or switch to method syntax where bivariance is intentional. %% alt: Contravariant checking enforces parameter safety at compile time This matters because the TypeScript 6.0 ecosystem assumes strict mode. Third-party libraries ship types built for contravariance. Disabling strictFunctionTypes to silence errors creates a type system that diverges from reality, where the compiler promises safety it cannot enforce. Production teams need a clear migration path that preserves type safety while fixing legitimate variance violations. strictFunctionTypes by default, enforcing contravariant parameter checking for function properties and breaking callbacks that relied on bivariant behavior. Animal cannot safely be called with Dog under strict checking. foo x: T : void and foo: x: T = void determines variance behavior. any .Contravariance describes how function parameter types behave when assigning one function to another. The rule is counterintuitive at first: a function that accepts a more general parameter type can substitute for one that accepts a more specific type. In other words, if a callback expects Dog , you can safely pass a function that accepts Animal , but not the reverse. TypeScript enforces this through contravariant parameter checking when strictFunctionTypes is enabled. The reason this matters is that function consumers control what arguments they pass. When you register a callback with Array