diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index bf79edfcd9855..d9ca3f9dd4878 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -16156,36 +16156,38 @@ namespace ts {
             const restIndex = sourceRestType || targetRestType ? paramCount - 1 : -1;
 
             for (let i = 0; i < paramCount; i++) {
-                const sourceType = i === restIndex ? getRestTypeAtPosition(source, i) : getTypeAtPosition(source, i);
-                const targetType = i === restIndex ? getRestTypeAtPosition(target, i) : getTypeAtPosition(target, i);
-                // In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
-                // how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions,
-                // they naturally relate only contra-variantly). However, if the source and target parameters both have
-                // function types with a single call signature, we know we are relating two callback parameters. In
-                // that case it is sufficient to only relate the parameters of the signatures co-variantly because,
-                // similar to return values, callback parameters are output positions. This means that a Promise<T>,
-                // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant)
-                // with respect to T.
-                const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType));
-                const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType));
-                const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) &&
-                    (getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable);
-                let related = callbacks ?
-                    compareSignaturesRelated(targetSig!, sourceSig!, (checkMode & SignatureCheckMode.StrictArity) | (strictVariance ? SignatureCheckMode.StrictCallback : SignatureCheckMode.BivariantCallback), reportErrors, errorReporter, incompatibleErrorReporter, compareTypes, reportUnreliableMarkers) :
-                    !(checkMode & SignatureCheckMode.Callback) && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors);
-                // With strict arity, (x: number | undefined) => void is a subtype of (x?: number | undefined) => void
-                if (related && checkMode & SignatureCheckMode.StrictArity && i >= getMinArgumentCount(source) && i < getMinArgumentCount(target) && compareTypes(sourceType, targetType, /*reportErrors*/ false)) {
-                    related = Ternary.False;
-                }
-                if (!related) {
-                    if (reportErrors) {
-                        errorReporter!(Diagnostics.Types_of_parameters_0_and_1_are_incompatible,
-                            unescapeLeadingUnderscores(getParameterNameAtPosition(source, i)),
-                            unescapeLeadingUnderscores(getParameterNameAtPosition(target, i)));
+                const sourceType = i === restIndex ? getRestTypeAtPosition(source, i) : tryGetTypeAtPosition(source, i);
+                const targetType = i === restIndex ? getRestTypeAtPosition(target, i) : tryGetTypeAtPosition(target, i);
+                if (sourceType && targetType) {
+                    // In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
+                    // how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions,
+                    // they naturally relate only contra-variantly). However, if the source and target parameters both have
+                    // function types with a single call signature, we know we are relating two callback parameters. In
+                    // that case it is sufficient to only relate the parameters of the signatures co-variantly because,
+                    // similar to return values, callback parameters are output positions. This means that a Promise<T>,
+                    // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant)
+                    // with respect to T.
+                    const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType));
+                    const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType));
+                    const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) &&
+                        (getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable);
+                    let related = callbacks ?
+                        compareSignaturesRelated(targetSig!, sourceSig!, (checkMode & SignatureCheckMode.StrictArity) | (strictVariance ? SignatureCheckMode.StrictCallback : SignatureCheckMode.BivariantCallback), reportErrors, errorReporter, incompatibleErrorReporter, compareTypes, reportUnreliableMarkers) :
+                        !(checkMode & SignatureCheckMode.Callback) && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors);
+                    // With strict arity, (x: number | undefined) => void is a subtype of (x?: number | undefined) => void
+                    if (related && checkMode & SignatureCheckMode.StrictArity && i >= getMinArgumentCount(source) && i < getMinArgumentCount(target) && compareTypes(sourceType, targetType, /*reportErrors*/ false)) {
+                        related = Ternary.False;
                     }
-                    return Ternary.False;
+                    if (!related) {
+                        if (reportErrors) {
+                            errorReporter!(Diagnostics.Types_of_parameters_0_and_1_are_incompatible,
+                                unescapeLeadingUnderscores(getParameterNameAtPosition(source, i)),
+                                unescapeLeadingUnderscores(getParameterNameAtPosition(target, i)));
+                        }
+                        return Ternary.False;
+                    }
+                    result &= related;
                 }
-                result &= related;
             }
 
             if (!(checkMode & SignatureCheckMode.IgnoreReturnTypes)) {
diff --git a/tests/baselines/reference/unmatchedParameterPositions.js b/tests/baselines/reference/unmatchedParameterPositions.js
new file mode 100644
index 0000000000000..5859091fb0e94
--- /dev/null
+++ b/tests/baselines/reference/unmatchedParameterPositions.js
@@ -0,0 +1,13 @@
+//// [unmatchedParameterPositions.ts]
+// Repros from #40251
+
+declare let s: (...items: never[]) => never[];
+let t1: () => unknown[] = s;
+let t2: (...args: []) => unknown[] = s;
+
+
+//// [unmatchedParameterPositions.js]
+"use strict";
+// Repros from #40251
+var t1 = s;
+var t2 = s;
diff --git a/tests/baselines/reference/unmatchedParameterPositions.symbols b/tests/baselines/reference/unmatchedParameterPositions.symbols
new file mode 100644
index 0000000000000..cf7a7c19df6eb
--- /dev/null
+++ b/tests/baselines/reference/unmatchedParameterPositions.symbols
@@ -0,0 +1,16 @@
+=== tests/cases/compiler/unmatchedParameterPositions.ts ===
+// Repros from #40251
+
+declare let s: (...items: never[]) => never[];
+>s : Symbol(s, Decl(unmatchedParameterPositions.ts, 2, 11))
+>items : Symbol(items, Decl(unmatchedParameterPositions.ts, 2, 16))
+
+let t1: () => unknown[] = s;
+>t1 : Symbol(t1, Decl(unmatchedParameterPositions.ts, 3, 3))
+>s : Symbol(s, Decl(unmatchedParameterPositions.ts, 2, 11))
+
+let t2: (...args: []) => unknown[] = s;
+>t2 : Symbol(t2, Decl(unmatchedParameterPositions.ts, 4, 3))
+>args : Symbol(args, Decl(unmatchedParameterPositions.ts, 4, 9))
+>s : Symbol(s, Decl(unmatchedParameterPositions.ts, 2, 11))
+
diff --git a/tests/baselines/reference/unmatchedParameterPositions.types b/tests/baselines/reference/unmatchedParameterPositions.types
new file mode 100644
index 0000000000000..522ac7e0170c5
--- /dev/null
+++ b/tests/baselines/reference/unmatchedParameterPositions.types
@@ -0,0 +1,16 @@
+=== tests/cases/compiler/unmatchedParameterPositions.ts ===
+// Repros from #40251
+
+declare let s: (...items: never[]) => never[];
+>s : (...items: never[]) => never[]
+>items : never[]
+
+let t1: () => unknown[] = s;
+>t1 : () => unknown[]
+>s : (...items: never[]) => never[]
+
+let t2: (...args: []) => unknown[] = s;
+>t2 : () => unknown[]
+>args : []
+>s : (...items: never[]) => never[]
+
diff --git a/tests/cases/compiler/unmatchedParameterPositions.ts b/tests/cases/compiler/unmatchedParameterPositions.ts
new file mode 100644
index 0000000000000..91202eb49da8e
--- /dev/null
+++ b/tests/cases/compiler/unmatchedParameterPositions.ts
@@ -0,0 +1,7 @@
+// @strict: true
+
+// Repros from #40251
+
+declare let s: (...items: never[]) => never[];
+let t1: () => unknown[] = s;
+let t2: (...args: []) => unknown[] = s;