@@ -12842,6 +12842,22 @@ namespace ts {
12842
12842
related = isRelatedTo(s, t, reportErrors);
12843
12843
}
12844
12844
}
12845
+ else if (variance === Variance.Unmeasurable) {
12846
+ if (isTypeAny(s) || isTypeAny(t)) {
12847
+ // If the `s` or `t` type is `any`, even if the structural desugaring says that the types _shouldn't_
12848
+ // be relatable, it's very surprising if they're not - take `Component<Foo, any>` to `Component<Foo, Foo>` - even
12849
+ // if the `any` position is unmeasurable, it's incredibly surprising that such a reference wouldn't check out.
12850
+ // (In fact, any nonlinear relation involving `any` is usually surprising) Even if it's potentially not correct
12851
+ // according to our underlying structural rules, we persist that assumption here.
12852
+ related = Ternary.True;
12853
+ }
12854
+ else {
12855
+ // Even an `Unmeasurable` variance works out without a structural check if the source and target are _identical_.
12856
+ // We can't simply assume invariance, because `Unmeasurable` marks nonlinear relations, for example, a relation tained by
12857
+ // the `-?` modifier in a mapped type (where, no matter how the inputs are related, the outputs still might not be)
12858
+ related = relation === identityRelation ? isRelatedTo(s, t, /*reportErrors*/ false) : compareTypesIdentical(s, t);
12859
+ }
12860
+ }
12845
12861
else {
12846
12862
// In the invariant case we first compare covariantly, and only when that
12847
12863
// succeeds do we proceed to compare contravariantly. Thus, error elaboration
@@ -13200,12 +13216,18 @@ namespace ts {
13200
13216
return Ternary.False;
13201
13217
13202
13218
function relateVariances(sourceTypeArguments: ReadonlyArray<Type> | undefined, targetTypeArguments: ReadonlyArray<Type> | undefined, variances: Variance[]) {
13203
- if (some(variances, v => v === Variance.Unmeasurable)) {
13204
- return undefined;
13205
- }
13206
13219
if (result = typeArgumentsRelatedTo(sourceTypeArguments, targetTypeArguments, variances, reportErrors)) {
13207
13220
return result;
13208
13221
}
13222
+ if (some(variances, v => v === Variance.Unmeasurable)) {
13223
+ // If some type parameter was `Unmeasurable`, and we couldn't pass by assuming it was invariant, then we
13224
+ // have to allow a structural fallback check
13225
+ // We elide the variance-based error elaborations, since those might not be too helpful, since we'll potentially
13226
+ // be assuming identity of the type parameter.
13227
+ originalErrorInfo = undefined;
13228
+ errorInfo = saveErrorInfo;
13229
+ return undefined;
13230
+ }
13209
13231
const allowStructuralFallback = targetTypeArguments && hasCovariantVoidArgument(targetTypeArguments, variances);
13210
13232
varianceCheckFailed = !allowStructuralFallback;
13211
13233
// The type arguments did not relate appropriately, but it may be because we have no variance
0 commit comments