Typescript: Can't infer `void` from 0-arity function

Created on 15 Aug 2019  ·  13Comments  ·  Source: microsoft/TypeScript


TypeScript Version: 3.7.0-dev.20190815


Search Terms: void, inference, mixed, unknown, arity, 0-arity, function

Code

export declare function infer<Params, Done, Fail = Error>(
  handler?: (params: Params) => any
): (params: Params) => void;

const f = infer(() => {});

f();

Expected behavior:

No errors!

Actual behavior:

Expected 1 arguments, but got 0. ts(2554)

Playground Link: Link

Working as Intended

All 13 comments

The way you wrote it, the function expects exactly one parameter with type Params. Try this instead:

export declare function infer<Params extends any[], Done, Fail = Error>(
  handler?: (...params: Params) => any
): (...params: Params) => void;

const f = infer(() => {});

f(); // works!

@AlCalzone I need always 0 or 1 parameter

It shouldn't infer unknown, but void

declare var f: (params: void) => void

f() // fine

I would argue that I have exactly one parameter of type undefined 😂

@AlCalzone I need always 0 or 1 parameter

The easy way would be using overloads:

export declare function infer<Done, Fail = Error>(handler?: () => any): () => void;
export declare function infer<Param, Done, Fail = Error>(handler?: (param: Param) => any): (params: Param) => void;

const f1 = infer((a: number) => a+1);
f1(1);

const f2 = infer(() => {});
f2();

EDIT: Here's a fancy version with conditional types

export declare function infer<Params extends any[], Done, Fail = Error>(
  handler?: (...params: Params) => any
): Params extends [] | [any] // allow 1 or 2 params
  ? (...params: Params) => void
  : ["too many arguments"];

const f1 = infer((a: number) => a+1);
f1(1);

const f0 = infer(() => {});
f0();

const f2 = infer((a, b) => a+b);
f2(1,2); // error here

@AlCalzone this means changing public interface of generics tho, instead of one type I would need to pass tuples, first solution is the same, I already tried it, first generic becomes Done not Params

@AlCalzone

the function expects exactly one parameter with type

If this was true, then it would error early on

const f = infer(() => {}); // error would be here

If this was true, then it would error early on

No. The way you typed it, infer returns a function with exactly one argument of type Params. The error is raised at the call site.

No. The way you typed it, infer returns a function with exactly one argument of type Params. The error is raised at the call site.

This 👆

I don't think it should work like this, why not infer void as parameter type, instead of unknown?

export declare function infer<Params>(
  handler?: (params: Params) => void
): (params: Params) => void;

const f = infer(() => {}); // type is (params: unknown) => void
declare var f: (params: void) => void

f() // fine

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

It isn't working as intended :

It isn't working as you intended, but that doesn't mean it makes any sense to anyone else. Sorry.

Was this page helpful?
0 / 5 - 0 ratings