diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 4cc0bb7953184..a072308a373ca 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -16335,8 +16335,20 @@ namespace ts {
return false;
}
+ let optionParametersCount = 0;
+ if (!signature.hasRestParameter) {
+ const len = signature.parameters.length;
+ for (let i = len - 1; i >= 0; i--) {
+ const type = getTypeAtPosition(signature, i);
+ if (type.flags !== TypeFlags.Void) {
+ break;
+ }
+ optionParametersCount++;
+ }
+ }
+
// If the call is incomplete, we should skip the lower bound check.
- const hasEnoughArguments = argCount >= signature.minArgumentCount;
+ const hasEnoughArguments = argCount >= (signature.minArgumentCount - optionParametersCount);
return callIsIncomplete || hasEnoughArguments;
}
diff --git a/tests/baselines/reference/arrayFrom.types b/tests/baselines/reference/arrayFrom.types
index f6a04dc442357..b8a0474c64ccd 100644
--- a/tests/baselines/reference/arrayFrom.types
+++ b/tests/baselines/reference/arrayFrom.types
@@ -37,7 +37,7 @@ const inputALike: ArrayLike = { length: 0 };
const inputARand = getEither(inputA, inputALike);
>inputARand : ArrayLike | Iterable
>getEither(inputA, inputALike) : ArrayLike | Iterable
->getEither : (in1: Iterable, in2: ArrayLike) => Iterable | ArrayLike
+>getEither : (in1: Iterable, in2: ArrayLike) => ArrayLike | Iterable
>inputA : A[]
>inputALike : ArrayLike
@@ -153,7 +153,7 @@ const result9: B[] = Array.from(inputARand, ({ a }): B => ({ b: a }));
// the ?: as always taking the false branch, narrowing to ArrayLike,
// even when the type is written as : Iterable|ArrayLike
function getEither (in1: Iterable, in2: ArrayLike) {
->getEither : (in1: Iterable, in2: ArrayLike) => Iterable | ArrayLike
+>getEither : (in1: Iterable, in2: ArrayLike) => ArrayLike | Iterable
>T : T
>in1 : Iterable
>Iterable : Iterable
@@ -163,7 +163,7 @@ function getEither (in1: Iterable, in2: ArrayLike) {
>T : T
return Math.random() > 0.5 ? in1 : in2;
->Math.random() > 0.5 ? in1 : in2 : Iterable | ArrayLike
+>Math.random() > 0.5 ? in1 : in2 : ArrayLike | Iterable
>Math.random() > 0.5 : boolean
>Math.random() : number
>Math.random : () => number
diff --git a/tests/baselines/reference/functionCallWithVoidParameter.errors.txt b/tests/baselines/reference/functionCallWithVoidParameter.errors.txt
new file mode 100644
index 0000000000000..88857d783f647
--- /dev/null
+++ b/tests/baselines/reference/functionCallWithVoidParameter.errors.txt
@@ -0,0 +1,71 @@
+tests/cases/conformance/functions/functionCallWithVoidParameter.ts(16,1): error TS2554: Expected 1 arguments, but got 0.
+tests/cases/conformance/functions/functionCallWithVoidParameter.ts(19,1): error TS2554: Expected 2 arguments, but got 0.
+tests/cases/conformance/functions/functionCallWithVoidParameter.ts(24,1): error TS2554: Expected 2 arguments, but got 0.
+tests/cases/conformance/functions/functionCallWithVoidParameter.ts(25,1): error TS2554: Expected 2 arguments, but got 1.
+tests/cases/conformance/functions/functionCallWithVoidParameter.ts(26,1): error TS2554: Expected 2 arguments, but got 1.
+tests/cases/conformance/functions/functionCallWithVoidParameter.ts(31,1): error TS2554: Expected 2 arguments, but got 0.
+tests/cases/conformance/functions/functionCallWithVoidParameter.ts(32,1): error TS2554: Expected 2 arguments, but got 1.
+
+
+==== tests/cases/conformance/functions/functionCallWithVoidParameter.ts (7 errors) ====
+ function f1(a: number, b: void) { }
+ function f2(a: void) { }
+ function f3(a: void, b: number) { }
+ function f4(a: number | void) { }
+ function f5(a: number | void, b: void) { }
+ function f6(a: number | void, b: number | void) { }
+ function f7(a: void, b: number | void) { }
+ function f8(a: void, b: void) { }
+ function f9(a: T, b: U) {}
+
+ f1(1);
+ f1(1, void 0);
+ f2();
+ f2(void 0);
+ f3(void 0, 1);
+ f4();
+ ~~~~
+!!! error TS2554: Expected 1 arguments, but got 0.
+ f4(1);
+ f4(void 0);
+ f5();
+ ~~~~
+!!! error TS2554: Expected 2 arguments, but got 0.
+ f5(1);
+ f5(1, void 0);
+ f5(void 0, void 0);
+ f5(void 0);
+ f6();
+ ~~~~
+!!! error TS2554: Expected 2 arguments, but got 0.
+ f6(1);
+ ~~~~~
+!!! error TS2554: Expected 2 arguments, but got 1.
+ f6(void 0);
+ ~~~~~~~~~~
+!!! error TS2554: Expected 2 arguments, but got 1.
+ f6(1, 1);
+ f6(1, void 0);
+ f6(void 0, void 0);
+ f6(void 0, 1);
+ f7();
+ ~~~~
+!!! error TS2554: Expected 2 arguments, but got 0.
+ f7(void 0);
+ ~~~~~~~~~~
+!!! error TS2554: Expected 2 arguments, but got 1.
+ f7(void 0, 1);
+ f7(void 0, void 0);
+ f8();
+ f8(void 0);
+ f8(void 0, void 0);
+
+ class X
+ {
+ f(t: T) { return { a: t }; }
+ }
+
+ var x2: X;
+ const t2b = x2.f();
+ t2b.a = void 0;
+
\ No newline at end of file
diff --git a/tests/baselines/reference/functionCallWithVoidParameter.js b/tests/baselines/reference/functionCallWithVoidParameter.js
new file mode 100644
index 0000000000000..2dd50b8f18322
--- /dev/null
+++ b/tests/baselines/reference/functionCallWithVoidParameter.js
@@ -0,0 +1,95 @@
+//// [functionCallWithVoidParameter.ts]
+function f1(a: number, b: void) { }
+function f2(a: void) { }
+function f3(a: void, b: number) { }
+function f4(a: number | void) { }
+function f5(a: number | void, b: void) { }
+function f6(a: number | void, b: number | void) { }
+function f7(a: void, b: number | void) { }
+function f8(a: void, b: void) { }
+function f9(a: T, b: U) {}
+
+f1(1);
+f1(1, void 0);
+f2();
+f2(void 0);
+f3(void 0, 1);
+f4();
+f4(1);
+f4(void 0);
+f5();
+f5(1);
+f5(1, void 0);
+f5(void 0, void 0);
+f5(void 0);
+f6();
+f6(1);
+f6(void 0);
+f6(1, 1);
+f6(1, void 0);
+f6(void 0, void 0);
+f6(void 0, 1);
+f7();
+f7(void 0);
+f7(void 0, 1);
+f7(void 0, void 0);
+f8();
+f8(void 0);
+f8(void 0, void 0);
+
+class X
+{
+ f(t: T) { return { a: t }; }
+}
+
+var x2: X;
+const t2b = x2.f();
+t2b.a = void 0;
+
+
+//// [functionCallWithVoidParameter.js]
+function f1(a, b) { }
+function f2(a) { }
+function f3(a, b) { }
+function f4(a) { }
+function f5(a, b) { }
+function f6(a, b) { }
+function f7(a, b) { }
+function f8(a, b) { }
+function f9(a, b) { }
+f1(1);
+f1(1, void 0);
+f2();
+f2(void 0);
+f3(void 0, 1);
+f4();
+f4(1);
+f4(void 0);
+f5();
+f5(1);
+f5(1, void 0);
+f5(void 0, void 0);
+f5(void 0);
+f6();
+f6(1);
+f6(void 0);
+f6(1, 1);
+f6(1, void 0);
+f6(void 0, void 0);
+f6(void 0, 1);
+f7();
+f7(void 0);
+f7(void 0, 1);
+f7(void 0, void 0);
+f8();
+f8(void 0);
+f8(void 0, void 0);
+var X = /** @class */ (function () {
+ function X() {
+ }
+ X.prototype.f = function (t) { return { a: t }; };
+ return X;
+}());
+var x2;
+var t2b = x2.f();
+t2b.a = void 0;
diff --git a/tests/baselines/reference/functionCallWithVoidParameter.symbols b/tests/baselines/reference/functionCallWithVoidParameter.symbols
new file mode 100644
index 0000000000000..ec30c66477b67
--- /dev/null
+++ b/tests/baselines/reference/functionCallWithVoidParameter.symbols
@@ -0,0 +1,156 @@
+=== tests/cases/conformance/functions/functionCallWithVoidParameter.ts ===
+function f1(a: number, b: void) { }
+>f1 : Symbol(f1, Decl(functionCallWithVoidParameter.ts, 0, 0))
+>a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 0, 12))
+>b : Symbol(b, Decl(functionCallWithVoidParameter.ts, 0, 22))
+
+function f2(a: void) { }
+>f2 : Symbol(f2, Decl(functionCallWithVoidParameter.ts, 0, 35))
+>a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 1, 12))
+
+function f3(a: void, b: number) { }
+>f3 : Symbol(f3, Decl(functionCallWithVoidParameter.ts, 1, 24))
+>a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 2, 12))
+>b : Symbol(b, Decl(functionCallWithVoidParameter.ts, 2, 20))
+
+function f4(a: number | void) { }
+>f4 : Symbol(f4, Decl(functionCallWithVoidParameter.ts, 2, 35))
+>a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 3, 12))
+
+function f5(a: number | void, b: void) { }
+>f5 : Symbol(f5, Decl(functionCallWithVoidParameter.ts, 3, 33))
+>a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 4, 12))
+>b : Symbol(b, Decl(functionCallWithVoidParameter.ts, 4, 29))
+
+function f6(a: number | void, b: number | void) { }
+>f6 : Symbol(f6, Decl(functionCallWithVoidParameter.ts, 4, 42))
+>a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 5, 12))
+>b : Symbol(b, Decl(functionCallWithVoidParameter.ts, 5, 29))
+
+function f7(a: void, b: number | void) { }
+>f7 : Symbol(f7, Decl(functionCallWithVoidParameter.ts, 5, 51))
+>a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 6, 12))
+>b : Symbol(b, Decl(functionCallWithVoidParameter.ts, 6, 20))
+
+function f8(a: void, b: void) { }
+>f8 : Symbol(f8, Decl(functionCallWithVoidParameter.ts, 6, 42))
+>a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 7, 12))
+>b : Symbol(b, Decl(functionCallWithVoidParameter.ts, 7, 20))
+
+function f9(a: T, b: U) {}
+>f9 : Symbol(f9, Decl(functionCallWithVoidParameter.ts, 7, 33))
+>T : Symbol(T, Decl(functionCallWithVoidParameter.ts, 8, 12))
+>U : Symbol(U, Decl(functionCallWithVoidParameter.ts, 8, 14))
+>a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 8, 18))
+>T : Symbol(T, Decl(functionCallWithVoidParameter.ts, 8, 12))
+>b : Symbol(b, Decl(functionCallWithVoidParameter.ts, 8, 23))
+>U : Symbol(U, Decl(functionCallWithVoidParameter.ts, 8, 14))
+
+f1(1);
+>f1 : Symbol(f1, Decl(functionCallWithVoidParameter.ts, 0, 0))
+
+f1(1, void 0);
+>f1 : Symbol(f1, Decl(functionCallWithVoidParameter.ts, 0, 0))
+
+f2();
+>f2 : Symbol(f2, Decl(functionCallWithVoidParameter.ts, 0, 35))
+
+f2(void 0);
+>f2 : Symbol(f2, Decl(functionCallWithVoidParameter.ts, 0, 35))
+
+f3(void 0, 1);
+>f3 : Symbol(f3, Decl(functionCallWithVoidParameter.ts, 1, 24))
+
+f4();
+>f4 : Symbol(f4, Decl(functionCallWithVoidParameter.ts, 2, 35))
+
+f4(1);
+>f4 : Symbol(f4, Decl(functionCallWithVoidParameter.ts, 2, 35))
+
+f4(void 0);
+>f4 : Symbol(f4, Decl(functionCallWithVoidParameter.ts, 2, 35))
+
+f5();
+>f5 : Symbol(f5, Decl(functionCallWithVoidParameter.ts, 3, 33))
+
+f5(1);
+>f5 : Symbol(f5, Decl(functionCallWithVoidParameter.ts, 3, 33))
+
+f5(1, void 0);
+>f5 : Symbol(f5, Decl(functionCallWithVoidParameter.ts, 3, 33))
+
+f5(void 0, void 0);
+>f5 : Symbol(f5, Decl(functionCallWithVoidParameter.ts, 3, 33))
+
+f5(void 0);
+>f5 : Symbol(f5, Decl(functionCallWithVoidParameter.ts, 3, 33))
+
+f6();
+>f6 : Symbol(f6, Decl(functionCallWithVoidParameter.ts, 4, 42))
+
+f6(1);
+>f6 : Symbol(f6, Decl(functionCallWithVoidParameter.ts, 4, 42))
+
+f6(void 0);
+>f6 : Symbol(f6, Decl(functionCallWithVoidParameter.ts, 4, 42))
+
+f6(1, 1);
+>f6 : Symbol(f6, Decl(functionCallWithVoidParameter.ts, 4, 42))
+
+f6(1, void 0);
+>f6 : Symbol(f6, Decl(functionCallWithVoidParameter.ts, 4, 42))
+
+f6(void 0, void 0);
+>f6 : Symbol(f6, Decl(functionCallWithVoidParameter.ts, 4, 42))
+
+f6(void 0, 1);
+>f6 : Symbol(f6, Decl(functionCallWithVoidParameter.ts, 4, 42))
+
+f7();
+>f7 : Symbol(f7, Decl(functionCallWithVoidParameter.ts, 5, 51))
+
+f7(void 0);
+>f7 : Symbol(f7, Decl(functionCallWithVoidParameter.ts, 5, 51))
+
+f7(void 0, 1);
+>f7 : Symbol(f7, Decl(functionCallWithVoidParameter.ts, 5, 51))
+
+f7(void 0, void 0);
+>f7 : Symbol(f7, Decl(functionCallWithVoidParameter.ts, 5, 51))
+
+f8();
+>f8 : Symbol(f8, Decl(functionCallWithVoidParameter.ts, 6, 42))
+
+f8(void 0);
+>f8 : Symbol(f8, Decl(functionCallWithVoidParameter.ts, 6, 42))
+
+f8(void 0, void 0);
+>f8 : Symbol(f8, Decl(functionCallWithVoidParameter.ts, 6, 42))
+
+class X
+>X : Symbol(X, Decl(functionCallWithVoidParameter.ts, 36, 19))
+>T : Symbol(T, Decl(functionCallWithVoidParameter.ts, 38, 8))
+{
+ f(t: T) { return { a: t }; }
+>f : Symbol(X.f, Decl(functionCallWithVoidParameter.ts, 39, 1))
+>t : Symbol(t, Decl(functionCallWithVoidParameter.ts, 40, 6))
+>T : Symbol(T, Decl(functionCallWithVoidParameter.ts, 38, 8))
+>a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 40, 22))
+>t : Symbol(t, Decl(functionCallWithVoidParameter.ts, 40, 6))
+}
+
+var x2: X;
+>x2 : Symbol(x2, Decl(functionCallWithVoidParameter.ts, 43, 3))
+>X : Symbol(X, Decl(functionCallWithVoidParameter.ts, 36, 19))
+
+const t2b = x2.f();
+>t2b : Symbol(t2b, Decl(functionCallWithVoidParameter.ts, 44, 5))
+>x2.f : Symbol(X.f, Decl(functionCallWithVoidParameter.ts, 39, 1))
+>x2 : Symbol(x2, Decl(functionCallWithVoidParameter.ts, 43, 3))
+>f : Symbol(X.f, Decl(functionCallWithVoidParameter.ts, 39, 1))
+
+t2b.a = void 0;
+>t2b.a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 40, 22))
+>t2b : Symbol(t2b, Decl(functionCallWithVoidParameter.ts, 44, 5))
+>a : Symbol(a, Decl(functionCallWithVoidParameter.ts, 40, 22))
+
diff --git a/tests/baselines/reference/functionCallWithVoidParameter.types b/tests/baselines/reference/functionCallWithVoidParameter.types
new file mode 100644
index 0000000000000..40528e1c9b188
--- /dev/null
+++ b/tests/baselines/reference/functionCallWithVoidParameter.types
@@ -0,0 +1,240 @@
+=== tests/cases/conformance/functions/functionCallWithVoidParameter.ts ===
+function f1(a: number, b: void) { }
+>f1 : (a: number, b: void) => void
+>a : number
+>b : void
+
+function f2(a: void) { }
+>f2 : (a: void) => void
+>a : void
+
+function f3(a: void, b: number) { }
+>f3 : (a: void, b: number) => void
+>a : void
+>b : number
+
+function f4(a: number | void) { }
+>f4 : (a: number | void) => void
+>a : number | void
+
+function f5(a: number | void, b: void) { }
+>f5 : (a: number | void, b: void) => void
+>a : number | void
+>b : void
+
+function f6(a: number | void, b: number | void) { }
+>f6 : (a: number | void, b: number | void) => void
+>a : number | void
+>b : number | void
+
+function f7(a: void, b: number | void) { }
+>f7 : (a: void, b: number | void) => void
+>a : void
+>b : number | void
+
+function f8(a: void, b: void) { }
+>f8 : (a: void, b: void) => void
+>a : void
+>b : void
+
+function f9(a: T, b: U) {}
+>f9 : (a: T, b: U) => void
+>T : T
+>U : U
+>a : T
+>T : T
+>b : U
+>U : U
+
+f1(1);
+>f1(1) : void
+>f1 : (a: number, b: void) => void
+>1 : 1
+
+f1(1, void 0);
+>f1(1, void 0) : void
+>f1 : (a: number, b: void) => void
+>1 : 1
+>void 0 : undefined
+>0 : 0
+
+f2();
+>f2() : void
+>f2 : (a: void) => void
+
+f2(void 0);
+>f2(void 0) : void
+>f2 : (a: void) => void
+>void 0 : undefined
+>0 : 0
+
+f3(void 0, 1);
+>f3(void 0, 1) : void
+>f3 : (a: void, b: number) => void
+>void 0 : undefined
+>0 : 0
+>1 : 1
+
+f4();
+>f4() : void
+>f4 : (a: number | void) => void
+
+f4(1);
+>f4(1) : void
+>f4 : (a: number | void) => void
+>1 : 1
+
+f4(void 0);
+>f4(void 0) : void
+>f4 : (a: number | void) => void
+>void 0 : undefined
+>0 : 0
+
+f5();
+>f5() : void
+>f5 : (a: number | void, b: void) => void
+
+f5(1);
+>f5(1) : void
+>f5 : (a: number | void, b: void) => void
+>1 : 1
+
+f5(1, void 0);
+>f5(1, void 0) : void
+>f5 : (a: number | void, b: void) => void
+>1 : 1
+>void 0 : undefined
+>0 : 0
+
+f5(void 0, void 0);
+>f5(void 0, void 0) : void
+>f5 : (a: number | void, b: void) => void
+>void 0 : undefined
+>0 : 0
+>void 0 : undefined
+>0 : 0
+
+f5(void 0);
+>f5(void 0) : void
+>f5 : (a: number | void, b: void) => void
+>void 0 : undefined
+>0 : 0
+
+f6();
+>f6() : void
+>f6 : (a: number | void, b: number | void) => void
+
+f6(1);
+>f6(1) : void
+>f6 : (a: number | void, b: number | void) => void
+>1 : 1
+
+f6(void 0);
+>f6(void 0) : void
+>f6 : (a: number | void, b: number | void) => void
+>void 0 : undefined
+>0 : 0
+
+f6(1, 1);
+>f6(1, 1) : void
+>f6 : (a: number | void, b: number | void) => void
+>1 : 1
+>1 : 1
+
+f6(1, void 0);
+>f6(1, void 0) : void
+>f6 : (a: number | void, b: number | void) => void
+>1 : 1
+>void 0 : undefined
+>0 : 0
+
+f6(void 0, void 0);
+>f6(void 0, void 0) : void
+>f6 : (a: number | void, b: number | void) => void
+>void 0 : undefined
+>0 : 0
+>void 0 : undefined
+>0 : 0
+
+f6(void 0, 1);
+>f6(void 0, 1) : void
+>f6 : (a: number | void, b: number | void) => void
+>void 0 : undefined
+>0 : 0
+>1 : 1
+
+f7();
+>f7() : void
+>f7 : (a: void, b: number | void) => void
+
+f7(void 0);
+>f7(void 0) : void
+>f7 : (a: void, b: number | void) => void
+>void 0 : undefined
+>0 : 0
+
+f7(void 0, 1);
+>f7(void 0, 1) : void
+>f7 : (a: void, b: number | void) => void
+>void 0 : undefined
+>0 : 0
+>1 : 1
+
+f7(void 0, void 0);
+>f7(void 0, void 0) : void
+>f7 : (a: void, b: number | void) => void
+>void 0 : undefined
+>0 : 0
+>void 0 : undefined
+>0 : 0
+
+f8();
+>f8() : void
+>f8 : (a: void, b: void) => void
+
+f8(void 0);
+>f8(void 0) : void
+>f8 : (a: void, b: void) => void
+>void 0 : undefined
+>0 : 0
+
+f8(void 0, void 0);
+>f8(void 0, void 0) : void
+>f8 : (a: void, b: void) => void
+>void 0 : undefined
+>0 : 0
+>void 0 : undefined
+>0 : 0
+
+class X
+>X : X
+>T : T
+{
+ f(t: T) { return { a: t }; }
+>f : (t: T) => { a: T; }
+>t : T
+>T : T
+>{ a: t } : { a: T; }
+>a : T
+>t : T
+}
+
+var x2: X;
+>x2 : X
+>X : X
+
+const t2b = x2.f();
+>t2b : { a: void; }
+>x2.f() : { a: void; }
+>x2.f : (t: void) => { a: void; }
+>x2 : X
+>f : (t: void) => { a: void; }
+
+t2b.a = void 0;
+>t2b.a = void 0 : undefined
+>t2b.a : void
+>t2b : { a: void; }
+>a : void
+>void 0 : undefined
+>0 : 0
+
diff --git a/tests/cases/conformance/functions/functionCallWithVoidParameter.ts b/tests/cases/conformance/functions/functionCallWithVoidParameter.ts
new file mode 100644
index 0000000000000..0f4665448b428
--- /dev/null
+++ b/tests/cases/conformance/functions/functionCallWithVoidParameter.ts
@@ -0,0 +1,46 @@
+function f1(a: number, b: void) { }
+function f2(a: void) { }
+function f3(a: void, b: number) { }
+function f4(a: number | void) { }
+function f5(a: number | void, b: void) { }
+function f6(a: number | void, b: number | void) { }
+function f7(a: void, b: number | void) { }
+function f8(a: void, b: void) { }
+function f9(a: T, b: U) {}
+
+f1(1);
+f1(1, void 0);
+f2();
+f2(void 0);
+f3(void 0, 1);
+f4();
+f4(1);
+f4(void 0);
+f5();
+f5(1);
+f5(1, void 0);
+f5(void 0, void 0);
+f5(void 0);
+f6();
+f6(1);
+f6(void 0);
+f6(1, 1);
+f6(1, void 0);
+f6(void 0, void 0);
+f6(void 0, 1);
+f7();
+f7(void 0);
+f7(void 0, 1);
+f7(void 0, void 0);
+f8();
+f8(void 0);
+f8(void 0, void 0);
+
+class X
+{
+ f(t: T) { return { a: t }; }
+}
+
+var x2: X;
+const t2b = x2.f();
+t2b.a = void 0;