Stricter generic signature checks by ahejlsberg · Pull Request #16368 · microsoft/TypeScript (original) (raw)
This PR complements #16305 by implementing stricter checking of type relationships for generic signatures. Previously, when checking type relationships for generic signatures we would always first erase type parameters (by substituting type any
for the type parameters). Now, we properly unify the type parameters by first inferring from the target signature to the source signature and then instantiating the source signature with the inferences. For example:
type A = <T, U>(x: T, y: U) => [T, U];
type B = (x: S, y: S) => [S, S];
function f(a: A, b: B) { a = b; // Error b = a; // Ok }
Previously, no errors were reported above because S
, T
, and U
were replaced by any
, causing the signatures to become identical. Now, once we unify the type parameters we can correctly determine that A
is assignable to B
, but not vice versa. Specifically, in the first assignment we infer T | U
for S
which after instantiation yields a signature that isn't assignable to A
, whereas in the second assignment we infer S
for each of T
and U
which after instantiation yields the same signature as B
.
Note that we perform unification only when the source and target types each have a single signature. When either the source or target has multiple signatures (i.e. overloads) we still resort to type parameter erasure as it otherwise becomes prohibitively expensive to determine the relationships.
This PR is technically a breaking change as we now uncover errors we previously wouldn't catch. For this reason we have included a --noStrictGenericChecks
compiler option to disable the stricter generic signature checks. Existing projects can use this as a stopgap solution until errors resulting from the stricter checking are corrected.