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;