mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 12:51:30 -05:00
Merge pull request #27522 from jack-williams/trailing-void-args-are-optional
Fix #4260 : Allow trailing arguments that accept void to be omitted
This commit is contained in:
@@ -18816,6 +18816,10 @@ namespace ts {
|
||||
return findIndex(args, isSpreadArgument);
|
||||
}
|
||||
|
||||
function acceptsVoid(t: Type): boolean {
|
||||
return !!(t.flags & TypeFlags.Void);
|
||||
}
|
||||
|
||||
function hasCorrectArity(node: CallLikeExpression, args: ReadonlyArray<Expression>, signature: Signature, signatureHelpTrailingComma = false) {
|
||||
let argCount: number;
|
||||
let callIsIncomplete = false; // In incomplete call we want to be lenient when we have too few arguments
|
||||
@@ -18877,8 +18881,16 @@ namespace ts {
|
||||
|
||||
// If the call is incomplete, we should skip the lower bound check.
|
||||
// JSX signatures can have extra parameters provided by the library which we don't check
|
||||
const hasEnoughArguments = argCount >= effectiveMinimumArguments;
|
||||
return callIsIncomplete || hasEnoughArguments;
|
||||
if (callIsIncomplete || argCount >= effectiveMinimumArguments) {
|
||||
return true;
|
||||
}
|
||||
for (let i = argCount; i < effectiveMinimumArguments; i++) {
|
||||
const type = getTypeAtPosition(signature, i);
|
||||
if (filterType(type, acceptsVoid).flags & TypeFlags.Never) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function hasCorrectTypeArgumentArity(signature: Signature, typeArguments: NodeArray<TypeNode> | undefined) {
|
||||
|
||||
131
tests/baselines/reference/callWithMissingVoid.errors.txt
Normal file
131
tests/baselines/reference/callWithMissingVoid.errors.txt
Normal file
@@ -0,0 +1,131 @@
|
||||
tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts(16,1): error TS2554: Expected 1 arguments, but got 0.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts(19,1): error TS2554: Expected 1 arguments, but got 0.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts(22,1): error TS2554: Expected 1 arguments, but got 0.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts(35,31): error TS2554: Expected 1 arguments, but got 0.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts(36,35): error TS2554: Expected 1 arguments, but got 0.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts(37,33): error TS2554: Expected 1 arguments, but got 0.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts(48,1): error TS2554: Expected 3 arguments, but got 1.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts(55,1): error TS2554: Expected 4 arguments, but got 2.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts(56,1): error TS2554: Expected 4 arguments, but got 3.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts(57,1): error TS2554: Expected 4 arguments, but got 1.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts(75,1): error TS2554: Expected 3 arguments, but got 1.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts (11 errors) ====
|
||||
// From #4260
|
||||
class X<T> {
|
||||
f(t: T) {
|
||||
return { a: t };
|
||||
}
|
||||
}
|
||||
|
||||
declare const x: X<void>;
|
||||
x.f() // no error because f expects void
|
||||
|
||||
declare const xUnion: X<void | number>;
|
||||
xUnion.f(42) // no error because f accepts number
|
||||
xUnion.f() // no error because f accepts void
|
||||
|
||||
declare const xAny: X<any>;
|
||||
xAny.f() // error, any still expects an argument
|
||||
~~~~~~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts:3:7: An argument for 't' was not provided.
|
||||
|
||||
declare const xUnknown: X<unknown>;
|
||||
xUnknown.f() // error, unknown still expects an argument
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts:3:7: An argument for 't' was not provided.
|
||||
|
||||
declare const xNever: X<never>;
|
||||
xNever.f() // error, never still expects an argument
|
||||
~~~~~~~~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts:3:7: An argument for 't' was not provided.
|
||||
|
||||
|
||||
// Promise has previously been updated to work without arguments, but to show this fixes the issue too.
|
||||
|
||||
class MyPromise<X> {
|
||||
constructor(executor: (resolve: (value: X) => void) => void) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
new MyPromise<void>(resolve => resolve()); // no error
|
||||
new MyPromise<void | number>(resolve => resolve()); // no error
|
||||
new MyPromise<any>(resolve => resolve()); // error, `any` arguments cannot be omitted
|
||||
~~~~~~~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts:28:38: An argument for 'value' was not provided.
|
||||
new MyPromise<unknown>(resolve => resolve()); // error, `unknown` arguments cannot be omitted
|
||||
~~~~~~~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts:28:38: An argument for 'value' was not provided.
|
||||
new MyPromise<never>(resolve => resolve()); // error, `never` arguments cannot be omitted
|
||||
~~~~~~~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts:28:38: An argument for 'value' was not provided.
|
||||
|
||||
|
||||
// Multiple parameters
|
||||
|
||||
function a(x: number, y: string, z: void): void {
|
||||
|
||||
}
|
||||
|
||||
a(4, "hello"); // ok
|
||||
a(4, "hello", void 0); // ok
|
||||
a(4); // not ok
|
||||
~~~~
|
||||
!!! error TS2554: Expected 3 arguments, but got 1.
|
||||
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts:42:23: An argument for 'y' was not provided.
|
||||
|
||||
function b(x: number, y: string, z: void, what: number): void {
|
||||
|
||||
}
|
||||
|
||||
b(4, "hello", void 0, 2); // ok
|
||||
b(4, "hello"); // not ok
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2554: Expected 4 arguments, but got 2.
|
||||
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts:50:34: An argument for 'z' was not provided.
|
||||
b(4, "hello", void 0); // not ok
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2554: Expected 4 arguments, but got 3.
|
||||
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts:50:43: An argument for 'what' was not provided.
|
||||
b(4); // not ok
|
||||
~~~~
|
||||
!!! error TS2554: Expected 4 arguments, but got 1.
|
||||
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts:50:23: An argument for 'y' was not provided.
|
||||
|
||||
function c(x: number | void, y: void, z: void | string | number): void {
|
||||
|
||||
}
|
||||
|
||||
c(3, void 0, void 0); // ok
|
||||
c(3, void 0); // ok
|
||||
c(3); // ok
|
||||
c(); // ok
|
||||
|
||||
|
||||
// Spread Parameters
|
||||
|
||||
declare function call<TS extends unknown[]>(
|
||||
handler: (...args: TS) => unknown,
|
||||
...args: TS): void;
|
||||
|
||||
call((x: number, y: number) => x + y) // error
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2554: Expected 3 arguments, but got 1.
|
||||
!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts:73:5: An argument for 'args' was not provided.
|
||||
call((x: number, y: number) => x + y, 4, 2) // ok
|
||||
|
||||
call((x: number, y: void) => x, 4, void 0) // ok
|
||||
call((x: number, y: void) => x, 4) // ok
|
||||
call((x: void, y: void) => 42) // ok
|
||||
call((x: number | void, y: number | void) => 42) // ok
|
||||
call((x: number | void, y: number | void) => 42, 4) // ok
|
||||
call((x: number | void, y: number | void) => 42, 4, 2) // ok
|
||||
|
||||
140
tests/baselines/reference/callWithMissingVoid.js
Normal file
140
tests/baselines/reference/callWithMissingVoid.js
Normal file
@@ -0,0 +1,140 @@
|
||||
//// [callWithMissingVoid.ts]
|
||||
// From #4260
|
||||
class X<T> {
|
||||
f(t: T) {
|
||||
return { a: t };
|
||||
}
|
||||
}
|
||||
|
||||
declare const x: X<void>;
|
||||
x.f() // no error because f expects void
|
||||
|
||||
declare const xUnion: X<void | number>;
|
||||
xUnion.f(42) // no error because f accepts number
|
||||
xUnion.f() // no error because f accepts void
|
||||
|
||||
declare const xAny: X<any>;
|
||||
xAny.f() // error, any still expects an argument
|
||||
|
||||
declare const xUnknown: X<unknown>;
|
||||
xUnknown.f() // error, unknown still expects an argument
|
||||
|
||||
declare const xNever: X<never>;
|
||||
xNever.f() // error, never still expects an argument
|
||||
|
||||
|
||||
// Promise has previously been updated to work without arguments, but to show this fixes the issue too.
|
||||
|
||||
class MyPromise<X> {
|
||||
constructor(executor: (resolve: (value: X) => void) => void) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
new MyPromise<void>(resolve => resolve()); // no error
|
||||
new MyPromise<void | number>(resolve => resolve()); // no error
|
||||
new MyPromise<any>(resolve => resolve()); // error, `any` arguments cannot be omitted
|
||||
new MyPromise<unknown>(resolve => resolve()); // error, `unknown` arguments cannot be omitted
|
||||
new MyPromise<never>(resolve => resolve()); // error, `never` arguments cannot be omitted
|
||||
|
||||
|
||||
// Multiple parameters
|
||||
|
||||
function a(x: number, y: string, z: void): void {
|
||||
|
||||
}
|
||||
|
||||
a(4, "hello"); // ok
|
||||
a(4, "hello", void 0); // ok
|
||||
a(4); // not ok
|
||||
|
||||
function b(x: number, y: string, z: void, what: number): void {
|
||||
|
||||
}
|
||||
|
||||
b(4, "hello", void 0, 2); // ok
|
||||
b(4, "hello"); // not ok
|
||||
b(4, "hello", void 0); // not ok
|
||||
b(4); // not ok
|
||||
|
||||
function c(x: number | void, y: void, z: void | string | number): void {
|
||||
|
||||
}
|
||||
|
||||
c(3, void 0, void 0); // ok
|
||||
c(3, void 0); // ok
|
||||
c(3); // ok
|
||||
c(); // ok
|
||||
|
||||
|
||||
// Spread Parameters
|
||||
|
||||
declare function call<TS extends unknown[]>(
|
||||
handler: (...args: TS) => unknown,
|
||||
...args: TS): void;
|
||||
|
||||
call((x: number, y: number) => x + y) // error
|
||||
call((x: number, y: number) => x + y, 4, 2) // ok
|
||||
|
||||
call((x: number, y: void) => x, 4, void 0) // ok
|
||||
call((x: number, y: void) => x, 4) // ok
|
||||
call((x: void, y: void) => 42) // ok
|
||||
call((x: number | void, y: number | void) => 42) // ok
|
||||
call((x: number | void, y: number | void) => 42, 4) // ok
|
||||
call((x: number | void, y: number | void) => 42, 4, 2) // ok
|
||||
|
||||
|
||||
//// [callWithMissingVoid.js]
|
||||
"use strict";
|
||||
// From #4260
|
||||
var X = /** @class */ (function () {
|
||||
function X() {
|
||||
}
|
||||
X.prototype.f = function (t) {
|
||||
return { a: t };
|
||||
};
|
||||
return X;
|
||||
}());
|
||||
x.f(); // no error because f expects void
|
||||
xUnion.f(42); // no error because f accepts number
|
||||
xUnion.f(); // no error because f accepts void
|
||||
xAny.f(); // error, any still expects an argument
|
||||
xUnknown.f(); // error, unknown still expects an argument
|
||||
xNever.f(); // error, never still expects an argument
|
||||
// Promise has previously been updated to work without arguments, but to show this fixes the issue too.
|
||||
var MyPromise = /** @class */ (function () {
|
||||
function MyPromise(executor) {
|
||||
}
|
||||
return MyPromise;
|
||||
}());
|
||||
new MyPromise(function (resolve) { return resolve(); }); // no error
|
||||
new MyPromise(function (resolve) { return resolve(); }); // no error
|
||||
new MyPromise(function (resolve) { return resolve(); }); // error, `any` arguments cannot be omitted
|
||||
new MyPromise(function (resolve) { return resolve(); }); // error, `unknown` arguments cannot be omitted
|
||||
new MyPromise(function (resolve) { return resolve(); }); // error, `never` arguments cannot be omitted
|
||||
// Multiple parameters
|
||||
function a(x, y, z) {
|
||||
}
|
||||
a(4, "hello"); // ok
|
||||
a(4, "hello", void 0); // ok
|
||||
a(4); // not ok
|
||||
function b(x, y, z, what) {
|
||||
}
|
||||
b(4, "hello", void 0, 2); // ok
|
||||
b(4, "hello"); // not ok
|
||||
b(4, "hello", void 0); // not ok
|
||||
b(4); // not ok
|
||||
function c(x, y, z) {
|
||||
}
|
||||
c(3, void 0, void 0); // ok
|
||||
c(3, void 0); // ok
|
||||
c(3); // ok
|
||||
c(); // ok
|
||||
call(function (x, y) { return x + y; }); // error
|
||||
call(function (x, y) { return x + y; }, 4, 2); // ok
|
||||
call(function (x, y) { return x; }, 4, void 0); // ok
|
||||
call(function (x, y) { return x; }, 4); // ok
|
||||
call(function (x, y) { return 42; }); // ok
|
||||
call(function (x, y) { return 42; }); // ok
|
||||
call(function (x, y) { return 42; }, 4); // ok
|
||||
call(function (x, y) { return 42; }, 4, 2); // ok
|
||||
231
tests/baselines/reference/callWithMissingVoid.symbols
Normal file
231
tests/baselines/reference/callWithMissingVoid.symbols
Normal file
@@ -0,0 +1,231 @@
|
||||
=== tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts ===
|
||||
// From #4260
|
||||
class X<T> {
|
||||
>X : Symbol(X, Decl(callWithMissingVoid.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(callWithMissingVoid.ts, 1, 8))
|
||||
|
||||
f(t: T) {
|
||||
>f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
>t : Symbol(t, Decl(callWithMissingVoid.ts, 2, 6))
|
||||
>T : Symbol(T, Decl(callWithMissingVoid.ts, 1, 8))
|
||||
|
||||
return { a: t };
|
||||
>a : Symbol(a, Decl(callWithMissingVoid.ts, 3, 16))
|
||||
>t : Symbol(t, Decl(callWithMissingVoid.ts, 2, 6))
|
||||
}
|
||||
}
|
||||
|
||||
declare const x: X<void>;
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 7, 13))
|
||||
>X : Symbol(X, Decl(callWithMissingVoid.ts, 0, 0))
|
||||
|
||||
x.f() // no error because f expects void
|
||||
>x.f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 7, 13))
|
||||
>f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
|
||||
declare const xUnion: X<void | number>;
|
||||
>xUnion : Symbol(xUnion, Decl(callWithMissingVoid.ts, 10, 13))
|
||||
>X : Symbol(X, Decl(callWithMissingVoid.ts, 0, 0))
|
||||
|
||||
xUnion.f(42) // no error because f accepts number
|
||||
>xUnion.f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
>xUnion : Symbol(xUnion, Decl(callWithMissingVoid.ts, 10, 13))
|
||||
>f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
|
||||
xUnion.f() // no error because f accepts void
|
||||
>xUnion.f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
>xUnion : Symbol(xUnion, Decl(callWithMissingVoid.ts, 10, 13))
|
||||
>f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
|
||||
declare const xAny: X<any>;
|
||||
>xAny : Symbol(xAny, Decl(callWithMissingVoid.ts, 14, 13))
|
||||
>X : Symbol(X, Decl(callWithMissingVoid.ts, 0, 0))
|
||||
|
||||
xAny.f() // error, any still expects an argument
|
||||
>xAny.f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
>xAny : Symbol(xAny, Decl(callWithMissingVoid.ts, 14, 13))
|
||||
>f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
|
||||
declare const xUnknown: X<unknown>;
|
||||
>xUnknown : Symbol(xUnknown, Decl(callWithMissingVoid.ts, 17, 13))
|
||||
>X : Symbol(X, Decl(callWithMissingVoid.ts, 0, 0))
|
||||
|
||||
xUnknown.f() // error, unknown still expects an argument
|
||||
>xUnknown.f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
>xUnknown : Symbol(xUnknown, Decl(callWithMissingVoid.ts, 17, 13))
|
||||
>f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
|
||||
declare const xNever: X<never>;
|
||||
>xNever : Symbol(xNever, Decl(callWithMissingVoid.ts, 20, 13))
|
||||
>X : Symbol(X, Decl(callWithMissingVoid.ts, 0, 0))
|
||||
|
||||
xNever.f() // error, never still expects an argument
|
||||
>xNever.f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
>xNever : Symbol(xNever, Decl(callWithMissingVoid.ts, 20, 13))
|
||||
>f : Symbol(X.f, Decl(callWithMissingVoid.ts, 1, 12))
|
||||
|
||||
|
||||
// Promise has previously been updated to work without arguments, but to show this fixes the issue too.
|
||||
|
||||
class MyPromise<X> {
|
||||
>MyPromise : Symbol(MyPromise, Decl(callWithMissingVoid.ts, 21, 10))
|
||||
>X : Symbol(X, Decl(callWithMissingVoid.ts, 26, 16))
|
||||
|
||||
constructor(executor: (resolve: (value: X) => void) => void) {
|
||||
>executor : Symbol(executor, Decl(callWithMissingVoid.ts, 27, 16))
|
||||
>resolve : Symbol(resolve, Decl(callWithMissingVoid.ts, 27, 27))
|
||||
>value : Symbol(value, Decl(callWithMissingVoid.ts, 27, 37))
|
||||
>X : Symbol(X, Decl(callWithMissingVoid.ts, 26, 16))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
new MyPromise<void>(resolve => resolve()); // no error
|
||||
>MyPromise : Symbol(MyPromise, Decl(callWithMissingVoid.ts, 21, 10))
|
||||
>resolve : Symbol(resolve, Decl(callWithMissingVoid.ts, 32, 20))
|
||||
>resolve : Symbol(resolve, Decl(callWithMissingVoid.ts, 32, 20))
|
||||
|
||||
new MyPromise<void | number>(resolve => resolve()); // no error
|
||||
>MyPromise : Symbol(MyPromise, Decl(callWithMissingVoid.ts, 21, 10))
|
||||
>resolve : Symbol(resolve, Decl(callWithMissingVoid.ts, 33, 29))
|
||||
>resolve : Symbol(resolve, Decl(callWithMissingVoid.ts, 33, 29))
|
||||
|
||||
new MyPromise<any>(resolve => resolve()); // error, `any` arguments cannot be omitted
|
||||
>MyPromise : Symbol(MyPromise, Decl(callWithMissingVoid.ts, 21, 10))
|
||||
>resolve : Symbol(resolve, Decl(callWithMissingVoid.ts, 34, 19))
|
||||
>resolve : Symbol(resolve, Decl(callWithMissingVoid.ts, 34, 19))
|
||||
|
||||
new MyPromise<unknown>(resolve => resolve()); // error, `unknown` arguments cannot be omitted
|
||||
>MyPromise : Symbol(MyPromise, Decl(callWithMissingVoid.ts, 21, 10))
|
||||
>resolve : Symbol(resolve, Decl(callWithMissingVoid.ts, 35, 23))
|
||||
>resolve : Symbol(resolve, Decl(callWithMissingVoid.ts, 35, 23))
|
||||
|
||||
new MyPromise<never>(resolve => resolve()); // error, `never` arguments cannot be omitted
|
||||
>MyPromise : Symbol(MyPromise, Decl(callWithMissingVoid.ts, 21, 10))
|
||||
>resolve : Symbol(resolve, Decl(callWithMissingVoid.ts, 36, 21))
|
||||
>resolve : Symbol(resolve, Decl(callWithMissingVoid.ts, 36, 21))
|
||||
|
||||
|
||||
// Multiple parameters
|
||||
|
||||
function a(x: number, y: string, z: void): void {
|
||||
>a : Symbol(a, Decl(callWithMissingVoid.ts, 36, 43))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 41, 11))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 41, 21))
|
||||
>z : Symbol(z, Decl(callWithMissingVoid.ts, 41, 32))
|
||||
|
||||
}
|
||||
|
||||
a(4, "hello"); // ok
|
||||
>a : Symbol(a, Decl(callWithMissingVoid.ts, 36, 43))
|
||||
|
||||
a(4, "hello", void 0); // ok
|
||||
>a : Symbol(a, Decl(callWithMissingVoid.ts, 36, 43))
|
||||
|
||||
a(4); // not ok
|
||||
>a : Symbol(a, Decl(callWithMissingVoid.ts, 36, 43))
|
||||
|
||||
function b(x: number, y: string, z: void, what: number): void {
|
||||
>b : Symbol(b, Decl(callWithMissingVoid.ts, 47, 5))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 49, 11))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 49, 21))
|
||||
>z : Symbol(z, Decl(callWithMissingVoid.ts, 49, 32))
|
||||
>what : Symbol(what, Decl(callWithMissingVoid.ts, 49, 41))
|
||||
|
||||
}
|
||||
|
||||
b(4, "hello", void 0, 2); // ok
|
||||
>b : Symbol(b, Decl(callWithMissingVoid.ts, 47, 5))
|
||||
|
||||
b(4, "hello"); // not ok
|
||||
>b : Symbol(b, Decl(callWithMissingVoid.ts, 47, 5))
|
||||
|
||||
b(4, "hello", void 0); // not ok
|
||||
>b : Symbol(b, Decl(callWithMissingVoid.ts, 47, 5))
|
||||
|
||||
b(4); // not ok
|
||||
>b : Symbol(b, Decl(callWithMissingVoid.ts, 47, 5))
|
||||
|
||||
function c(x: number | void, y: void, z: void | string | number): void {
|
||||
>c : Symbol(c, Decl(callWithMissingVoid.ts, 56, 5))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 58, 11))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 58, 28))
|
||||
>z : Symbol(z, Decl(callWithMissingVoid.ts, 58, 37))
|
||||
|
||||
}
|
||||
|
||||
c(3, void 0, void 0); // ok
|
||||
>c : Symbol(c, Decl(callWithMissingVoid.ts, 56, 5))
|
||||
|
||||
c(3, void 0); // ok
|
||||
>c : Symbol(c, Decl(callWithMissingVoid.ts, 56, 5))
|
||||
|
||||
c(3); // ok
|
||||
>c : Symbol(c, Decl(callWithMissingVoid.ts, 56, 5))
|
||||
|
||||
c(); // ok
|
||||
>c : Symbol(c, Decl(callWithMissingVoid.ts, 56, 5))
|
||||
|
||||
|
||||
// Spread Parameters
|
||||
|
||||
declare function call<TS extends unknown[]>(
|
||||
>call : Symbol(call, Decl(callWithMissingVoid.ts, 65, 4))
|
||||
>TS : Symbol(TS, Decl(callWithMissingVoid.ts, 70, 22))
|
||||
|
||||
handler: (...args: TS) => unknown,
|
||||
>handler : Symbol(handler, Decl(callWithMissingVoid.ts, 70, 44))
|
||||
>args : Symbol(args, Decl(callWithMissingVoid.ts, 71, 14))
|
||||
>TS : Symbol(TS, Decl(callWithMissingVoid.ts, 70, 22))
|
||||
|
||||
...args: TS): void;
|
||||
>args : Symbol(args, Decl(callWithMissingVoid.ts, 71, 38))
|
||||
>TS : Symbol(TS, Decl(callWithMissingVoid.ts, 70, 22))
|
||||
|
||||
call((x: number, y: number) => x + y) // error
|
||||
>call : Symbol(call, Decl(callWithMissingVoid.ts, 65, 4))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 74, 6))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 74, 16))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 74, 6))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 74, 16))
|
||||
|
||||
call((x: number, y: number) => x + y, 4, 2) // ok
|
||||
>call : Symbol(call, Decl(callWithMissingVoid.ts, 65, 4))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 75, 6))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 75, 16))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 75, 6))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 75, 16))
|
||||
|
||||
call((x: number, y: void) => x, 4, void 0) // ok
|
||||
>call : Symbol(call, Decl(callWithMissingVoid.ts, 65, 4))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 77, 6))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 77, 16))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 77, 6))
|
||||
|
||||
call((x: number, y: void) => x, 4) // ok
|
||||
>call : Symbol(call, Decl(callWithMissingVoid.ts, 65, 4))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 78, 6))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 78, 16))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 78, 6))
|
||||
|
||||
call((x: void, y: void) => 42) // ok
|
||||
>call : Symbol(call, Decl(callWithMissingVoid.ts, 65, 4))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 79, 6))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 79, 14))
|
||||
|
||||
call((x: number | void, y: number | void) => 42) // ok
|
||||
>call : Symbol(call, Decl(callWithMissingVoid.ts, 65, 4))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 80, 6))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 80, 23))
|
||||
|
||||
call((x: number | void, y: number | void) => 42, 4) // ok
|
||||
>call : Symbol(call, Decl(callWithMissingVoid.ts, 65, 4))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 81, 6))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 81, 23))
|
||||
|
||||
call((x: number | void, y: number | void) => 42, 4, 2) // ok
|
||||
>call : Symbol(call, Decl(callWithMissingVoid.ts, 65, 4))
|
||||
>x : Symbol(x, Decl(callWithMissingVoid.ts, 82, 6))
|
||||
>y : Symbol(y, Decl(callWithMissingVoid.ts, 82, 23))
|
||||
|
||||
312
tests/baselines/reference/callWithMissingVoid.types
Normal file
312
tests/baselines/reference/callWithMissingVoid.types
Normal file
@@ -0,0 +1,312 @@
|
||||
=== tests/cases/conformance/expressions/functionCalls/callWithMissingVoid.ts ===
|
||||
// From #4260
|
||||
class X<T> {
|
||||
>X : X<T>
|
||||
|
||||
f(t: T) {
|
||||
>f : (t: T) => { a: T; }
|
||||
>t : T
|
||||
|
||||
return { a: t };
|
||||
>{ a: t } : { a: T; }
|
||||
>a : T
|
||||
>t : T
|
||||
}
|
||||
}
|
||||
|
||||
declare const x: X<void>;
|
||||
>x : X<void>
|
||||
|
||||
x.f() // no error because f expects void
|
||||
>x.f() : { a: void; }
|
||||
>x.f : (t: void) => { a: void; }
|
||||
>x : X<void>
|
||||
>f : (t: void) => { a: void; }
|
||||
|
||||
declare const xUnion: X<void | number>;
|
||||
>xUnion : X<number | void>
|
||||
|
||||
xUnion.f(42) // no error because f accepts number
|
||||
>xUnion.f(42) : { a: number | void; }
|
||||
>xUnion.f : (t: number | void) => { a: number | void; }
|
||||
>xUnion : X<number | void>
|
||||
>f : (t: number | void) => { a: number | void; }
|
||||
>42 : 42
|
||||
|
||||
xUnion.f() // no error because f accepts void
|
||||
>xUnion.f() : { a: number | void; }
|
||||
>xUnion.f : (t: number | void) => { a: number | void; }
|
||||
>xUnion : X<number | void>
|
||||
>f : (t: number | void) => { a: number | void; }
|
||||
|
||||
declare const xAny: X<any>;
|
||||
>xAny : X<any>
|
||||
|
||||
xAny.f() // error, any still expects an argument
|
||||
>xAny.f() : { a: any; }
|
||||
>xAny.f : (t: any) => { a: any; }
|
||||
>xAny : X<any>
|
||||
>f : (t: any) => { a: any; }
|
||||
|
||||
declare const xUnknown: X<unknown>;
|
||||
>xUnknown : X<unknown>
|
||||
|
||||
xUnknown.f() // error, unknown still expects an argument
|
||||
>xUnknown.f() : { a: unknown; }
|
||||
>xUnknown.f : (t: unknown) => { a: unknown; }
|
||||
>xUnknown : X<unknown>
|
||||
>f : (t: unknown) => { a: unknown; }
|
||||
|
||||
declare const xNever: X<never>;
|
||||
>xNever : X<never>
|
||||
|
||||
xNever.f() // error, never still expects an argument
|
||||
>xNever.f() : { a: never; }
|
||||
>xNever.f : (t: never) => { a: never; }
|
||||
>xNever : X<never>
|
||||
>f : (t: never) => { a: never; }
|
||||
|
||||
|
||||
// Promise has previously been updated to work without arguments, but to show this fixes the issue too.
|
||||
|
||||
class MyPromise<X> {
|
||||
>MyPromise : MyPromise<X>
|
||||
|
||||
constructor(executor: (resolve: (value: X) => void) => void) {
|
||||
>executor : (resolve: (value: X) => void) => void
|
||||
>resolve : (value: X) => void
|
||||
>value : X
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
new MyPromise<void>(resolve => resolve()); // no error
|
||||
>new MyPromise<void>(resolve => resolve()) : MyPromise<void>
|
||||
>MyPromise : typeof MyPromise
|
||||
>resolve => resolve() : (resolve: (value: void) => void) => void
|
||||
>resolve : (value: void) => void
|
||||
>resolve() : void
|
||||
>resolve : (value: void) => void
|
||||
|
||||
new MyPromise<void | number>(resolve => resolve()); // no error
|
||||
>new MyPromise<void | number>(resolve => resolve()) : MyPromise<number | void>
|
||||
>MyPromise : typeof MyPromise
|
||||
>resolve => resolve() : (resolve: (value: number | void) => void) => void
|
||||
>resolve : (value: number | void) => void
|
||||
>resolve() : void
|
||||
>resolve : (value: number | void) => void
|
||||
|
||||
new MyPromise<any>(resolve => resolve()); // error, `any` arguments cannot be omitted
|
||||
>new MyPromise<any>(resolve => resolve()) : MyPromise<any>
|
||||
>MyPromise : typeof MyPromise
|
||||
>resolve => resolve() : (resolve: (value: any) => void) => any
|
||||
>resolve : (value: any) => void
|
||||
>resolve() : void
|
||||
>resolve : (value: any) => void
|
||||
|
||||
new MyPromise<unknown>(resolve => resolve()); // error, `unknown` arguments cannot be omitted
|
||||
>new MyPromise<unknown>(resolve => resolve()) : MyPromise<unknown>
|
||||
>MyPromise : typeof MyPromise
|
||||
>resolve => resolve() : (resolve: (value: unknown) => void) => any
|
||||
>resolve : (value: unknown) => void
|
||||
>resolve() : void
|
||||
>resolve : (value: unknown) => void
|
||||
|
||||
new MyPromise<never>(resolve => resolve()); // error, `never` arguments cannot be omitted
|
||||
>new MyPromise<never>(resolve => resolve()) : MyPromise<never>
|
||||
>MyPromise : typeof MyPromise
|
||||
>resolve => resolve() : (resolve: (value: never) => void) => any
|
||||
>resolve : (value: never) => void
|
||||
>resolve() : void
|
||||
>resolve : (value: never) => void
|
||||
|
||||
|
||||
// Multiple parameters
|
||||
|
||||
function a(x: number, y: string, z: void): void {
|
||||
>a : (x: number, y: string, z: void) => void
|
||||
>x : number
|
||||
>y : string
|
||||
>z : void
|
||||
|
||||
}
|
||||
|
||||
a(4, "hello"); // ok
|
||||
>a(4, "hello") : void
|
||||
>a : (x: number, y: string, z: void) => void
|
||||
>4 : 4
|
||||
>"hello" : "hello"
|
||||
|
||||
a(4, "hello", void 0); // ok
|
||||
>a(4, "hello", void 0) : void
|
||||
>a : (x: number, y: string, z: void) => void
|
||||
>4 : 4
|
||||
>"hello" : "hello"
|
||||
>void 0 : undefined
|
||||
>0 : 0
|
||||
|
||||
a(4); // not ok
|
||||
>a(4) : void
|
||||
>a : (x: number, y: string, z: void) => void
|
||||
>4 : 4
|
||||
|
||||
function b(x: number, y: string, z: void, what: number): void {
|
||||
>b : (x: number, y: string, z: void, what: number) => void
|
||||
>x : number
|
||||
>y : string
|
||||
>z : void
|
||||
>what : number
|
||||
|
||||
}
|
||||
|
||||
b(4, "hello", void 0, 2); // ok
|
||||
>b(4, "hello", void 0, 2) : void
|
||||
>b : (x: number, y: string, z: void, what: number) => void
|
||||
>4 : 4
|
||||
>"hello" : "hello"
|
||||
>void 0 : undefined
|
||||
>0 : 0
|
||||
>2 : 2
|
||||
|
||||
b(4, "hello"); // not ok
|
||||
>b(4, "hello") : void
|
||||
>b : (x: number, y: string, z: void, what: number) => void
|
||||
>4 : 4
|
||||
>"hello" : "hello"
|
||||
|
||||
b(4, "hello", void 0); // not ok
|
||||
>b(4, "hello", void 0) : void
|
||||
>b : (x: number, y: string, z: void, what: number) => void
|
||||
>4 : 4
|
||||
>"hello" : "hello"
|
||||
>void 0 : undefined
|
||||
>0 : 0
|
||||
|
||||
b(4); // not ok
|
||||
>b(4) : void
|
||||
>b : (x: number, y: string, z: void, what: number) => void
|
||||
>4 : 4
|
||||
|
||||
function c(x: number | void, y: void, z: void | string | number): void {
|
||||
>c : (x: number | void, y: void, z: string | number | void) => void
|
||||
>x : number | void
|
||||
>y : void
|
||||
>z : string | number | void
|
||||
|
||||
}
|
||||
|
||||
c(3, void 0, void 0); // ok
|
||||
>c(3, void 0, void 0) : void
|
||||
>c : (x: number | void, y: void, z: string | number | void) => void
|
||||
>3 : 3
|
||||
>void 0 : undefined
|
||||
>0 : 0
|
||||
>void 0 : undefined
|
||||
>0 : 0
|
||||
|
||||
c(3, void 0); // ok
|
||||
>c(3, void 0) : void
|
||||
>c : (x: number | void, y: void, z: string | number | void) => void
|
||||
>3 : 3
|
||||
>void 0 : undefined
|
||||
>0 : 0
|
||||
|
||||
c(3); // ok
|
||||
>c(3) : void
|
||||
>c : (x: number | void, y: void, z: string | number | void) => void
|
||||
>3 : 3
|
||||
|
||||
c(); // ok
|
||||
>c() : void
|
||||
>c : (x: number | void, y: void, z: string | number | void) => void
|
||||
|
||||
|
||||
// Spread Parameters
|
||||
|
||||
declare function call<TS extends unknown[]>(
|
||||
>call : <TS extends unknown[]>(handler: (...args: TS) => unknown, ...args: TS) => void
|
||||
|
||||
handler: (...args: TS) => unknown,
|
||||
>handler : (...args: TS) => unknown
|
||||
>args : TS
|
||||
|
||||
...args: TS): void;
|
||||
>args : TS
|
||||
|
||||
call((x: number, y: number) => x + y) // error
|
||||
>call((x: number, y: number) => x + y) : any
|
||||
>call : <TS extends unknown[]>(handler: (...args: TS) => unknown, ...args: TS) => void
|
||||
>(x: number, y: number) => x + y : (x: number, y: number) => number
|
||||
>x : number
|
||||
>y : number
|
||||
>x + y : number
|
||||
>x : number
|
||||
>y : number
|
||||
|
||||
call((x: number, y: number) => x + y, 4, 2) // ok
|
||||
>call((x: number, y: number) => x + y, 4, 2) : void
|
||||
>call : <TS extends unknown[]>(handler: (...args: TS) => unknown, ...args: TS) => void
|
||||
>(x: number, y: number) => x + y : (x: number, y: number) => number
|
||||
>x : number
|
||||
>y : number
|
||||
>x + y : number
|
||||
>x : number
|
||||
>y : number
|
||||
>4 : 4
|
||||
>2 : 2
|
||||
|
||||
call((x: number, y: void) => x, 4, void 0) // ok
|
||||
>call((x: number, y: void) => x, 4, void 0) : void
|
||||
>call : <TS extends unknown[]>(handler: (...args: TS) => unknown, ...args: TS) => void
|
||||
>(x: number, y: void) => x : (x: number, y: void) => number
|
||||
>x : number
|
||||
>y : void
|
||||
>x : number
|
||||
>4 : 4
|
||||
>void 0 : undefined
|
||||
>0 : 0
|
||||
|
||||
call((x: number, y: void) => x, 4) // ok
|
||||
>call((x: number, y: void) => x, 4) : void
|
||||
>call : <TS extends unknown[]>(handler: (...args: TS) => unknown, ...args: TS) => void
|
||||
>(x: number, y: void) => x : (x: number, y: void) => number
|
||||
>x : number
|
||||
>y : void
|
||||
>x : number
|
||||
>4 : 4
|
||||
|
||||
call((x: void, y: void) => 42) // ok
|
||||
>call((x: void, y: void) => 42) : void
|
||||
>call : <TS extends unknown[]>(handler: (...args: TS) => unknown, ...args: TS) => void
|
||||
>(x: void, y: void) => 42 : (x: void, y: void) => number
|
||||
>x : void
|
||||
>y : void
|
||||
>42 : 42
|
||||
|
||||
call((x: number | void, y: number | void) => 42) // ok
|
||||
>call((x: number | void, y: number | void) => 42) : void
|
||||
>call : <TS extends unknown[]>(handler: (...args: TS) => unknown, ...args: TS) => void
|
||||
>(x: number | void, y: number | void) => 42 : (x: number | void, y: number | void) => number
|
||||
>x : number | void
|
||||
>y : number | void
|
||||
>42 : 42
|
||||
|
||||
call((x: number | void, y: number | void) => 42, 4) // ok
|
||||
>call((x: number | void, y: number | void) => 42, 4) : void
|
||||
>call : <TS extends unknown[]>(handler: (...args: TS) => unknown, ...args: TS) => void
|
||||
>(x: number | void, y: number | void) => 42 : (x: number | void, y: number | void) => number
|
||||
>x : number | void
|
||||
>y : number | void
|
||||
>42 : 42
|
||||
>4 : 4
|
||||
|
||||
call((x: number | void, y: number | void) => 42, 4, 2) // ok
|
||||
>call((x: number | void, y: number | void) => 42, 4, 2) : void
|
||||
>call : <TS extends unknown[]>(handler: (...args: TS) => unknown, ...args: TS) => void
|
||||
>(x: number | void, y: number | void) => 42 : (x: number | void, y: number | void) => number
|
||||
>x : number | void
|
||||
>y : number | void
|
||||
>42 : 42
|
||||
>4 : 4
|
||||
>2 : 2
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
// @strict: true
|
||||
|
||||
// From #4260
|
||||
class X<T> {
|
||||
f(t: T) {
|
||||
return { a: t };
|
||||
}
|
||||
}
|
||||
|
||||
declare const x: X<void>;
|
||||
x.f() // no error because f expects void
|
||||
|
||||
declare const xUnion: X<void | number>;
|
||||
xUnion.f(42) // no error because f accepts number
|
||||
xUnion.f() // no error because f accepts void
|
||||
|
||||
declare const xAny: X<any>;
|
||||
xAny.f() // error, any still expects an argument
|
||||
|
||||
declare const xUnknown: X<unknown>;
|
||||
xUnknown.f() // error, unknown still expects an argument
|
||||
|
||||
declare const xNever: X<never>;
|
||||
xNever.f() // error, never still expects an argument
|
||||
|
||||
|
||||
// Promise has previously been updated to work without arguments, but to show this fixes the issue too.
|
||||
|
||||
class MyPromise<X> {
|
||||
constructor(executor: (resolve: (value: X) => void) => void) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
new MyPromise<void>(resolve => resolve()); // no error
|
||||
new MyPromise<void | number>(resolve => resolve()); // no error
|
||||
new MyPromise<any>(resolve => resolve()); // error, `any` arguments cannot be omitted
|
||||
new MyPromise<unknown>(resolve => resolve()); // error, `unknown` arguments cannot be omitted
|
||||
new MyPromise<never>(resolve => resolve()); // error, `never` arguments cannot be omitted
|
||||
|
||||
|
||||
// Multiple parameters
|
||||
|
||||
function a(x: number, y: string, z: void): void {
|
||||
|
||||
}
|
||||
|
||||
a(4, "hello"); // ok
|
||||
a(4, "hello", void 0); // ok
|
||||
a(4); // not ok
|
||||
|
||||
function b(x: number, y: string, z: void, what: number): void {
|
||||
|
||||
}
|
||||
|
||||
b(4, "hello", void 0, 2); // ok
|
||||
b(4, "hello"); // not ok
|
||||
b(4, "hello", void 0); // not ok
|
||||
b(4); // not ok
|
||||
|
||||
function c(x: number | void, y: void, z: void | string | number): void {
|
||||
|
||||
}
|
||||
|
||||
c(3, void 0, void 0); // ok
|
||||
c(3, void 0); // ok
|
||||
c(3); // ok
|
||||
c(); // ok
|
||||
|
||||
|
||||
// Spread Parameters
|
||||
|
||||
declare function call<TS extends unknown[]>(
|
||||
handler: (...args: TS) => unknown,
|
||||
...args: TS): void;
|
||||
|
||||
call((x: number, y: number) => x + y) // error
|
||||
call((x: number, y: number) => x + y, 4, 2) // ok
|
||||
|
||||
call((x: number, y: void) => x, 4, void 0) // ok
|
||||
call((x: number, y: void) => x, 4) // ok
|
||||
call((x: void, y: void) => 42) // ok
|
||||
call((x: number | void, y: number | void) => 42) // ok
|
||||
call((x: number | void, y: number | void) => 42, 4) // ok
|
||||
call((x: number | void, y: number | void) => 42, 4, 2) // ok
|
||||
Reference in New Issue
Block a user