Skip to content

Commit 8ae3e05

Browse files
committed
Treat callback parameters as strictly covariant
1 parent 3029b8f commit 8ae3e05

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

src/compiler/checker.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8157,7 +8157,8 @@ namespace ts {
81578157
function isSignatureAssignableTo(source: Signature,
81588158
target: Signature,
81598159
ignoreReturnTypes: boolean): boolean {
8160-
return compareSignaturesRelated(source, target, ignoreReturnTypes, /*reportErrors*/ false, /*errorReporter*/ undefined, compareTypesAssignable) !== Ternary.False;
8160+
return compareSignaturesRelated(source, target, /*strictVariance*/ false, ignoreReturnTypes, /*reportErrors*/ false,
8161+
/*errorReporter*/ undefined, compareTypesAssignable) !== Ternary.False;
81618162
}
81628163

81638164
type ErrorReporter = (message: DiagnosticMessage, arg0?: string, arg1?: string) => void;
@@ -8167,6 +8168,7 @@ namespace ts {
81678168
*/
81688169
function compareSignaturesRelated(source: Signature,
81698170
target: Signature,
8171+
strictVariance: boolean,
81708172
ignoreReturnTypes: boolean,
81718173
reportErrors: boolean,
81728174
errorReporter: ErrorReporter,
@@ -8209,9 +8211,17 @@ namespace ts {
82098211
const sourceParams = source.parameters;
82108212
const targetParams = target.parameters;
82118213
for (let i = 0; i < checkCount; i++) {
8212-
const s = i < sourceMax ? getTypeOfParameter(sourceParams[i]) : getRestTypeOfSignature(source);
8213-
const t = i < targetMax ? getTypeOfParameter(targetParams[i]) : getRestTypeOfSignature(target);
8214-
const related = compareTypes(s, t, /*reportErrors*/ false) || compareTypes(t, s, reportErrors);
8214+
const sourceType = i < sourceMax ? getTypeOfParameter(sourceParams[i]) : getRestTypeOfSignature(source);
8215+
const targetType = i < targetMax ? getTypeOfParameter(targetParams[i]) : getRestTypeOfSignature(target);
8216+
const sourceSig = getSingleCallSignature(sourceType);
8217+
const targetSig = getSingleCallSignature(targetType);
8218+
// If the source and target parameters both have function types with a single call signature we are
8219+
// relating two callback parameters. In that case we compare the callback signatures with strict
8220+
// variance, meaning we require the callback parameters to be pairwise co-variant (because, similar
8221+
// to return values, callback parameters are output positions).
8222+
const related = sourceSig && targetSig ?
8223+
compareSignaturesRelated(targetSig, sourceSig, /*strictVariance*/ true, /*ignoreReturnTypes*/ false, reportErrors, errorReporter, compareTypes) :
8224+
!strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors);
82158225
if (!related) {
82168226
if (reportErrors) {
82178227
errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible,
@@ -9210,7 +9220,7 @@ namespace ts {
92109220
* See signatureAssignableTo, compareSignaturesIdentical
92119221
*/
92129222
function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): Ternary {
9213-
return compareSignaturesRelated(source, target, /*ignoreReturnTypes*/ false, reportErrors, reportError, isRelatedTo);
9223+
return compareSignaturesRelated(source, target, /*strictVariance*/ false, /*ignoreReturnTypes*/ false, reportErrors, reportError, isRelatedTo);
92149224
}
92159225

92169226
function signaturesIdenticalTo(source: Type, target: Type, kind: SignatureKind): Ternary {

0 commit comments

Comments
 (0)