Estus Flask
Estus Flask

Reputation: 222503

Restrict function return value to void

bar is expected to be a function with no return value:

let foo = () => 'foo';
let bar: () => void = foo; // produces no error

Can bar be prevented from being assigned with a function that doesn't match expected () => void signature?

For example, in this case:

declare let jsApiThatShouldNeverAcceptTypeofFoo = (bar: () => void) => void;
jsApiThatShouldNeverAcceptTypeofFoo(bar);

Upvotes: 2

Views: 90

Answers (2)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249666

A partial workaround is to ensure that the return type of the function has no keys. This is satisfied by void, but also by {} and never. This might be close enough, as functions retuning never should throw an error and functions returning {} happen infrequently enough:

type EnsureVoid<T> = keyof T extends never ? 
    void 
    : "Should not have a return type, only ()=> void is allowed";

declare let jsApiThatShouldNeverAcceptTypeofFoo: <T extends EnsureVoid<T>>(bar: ()=> T) => void;

let foo = () => 'foo';
jsApiThatShouldNeverAcceptTypeofFoo(foo)  // Error 


let bar = () => { };
jsApiThatShouldNeverAcceptTypeofFoo(bar)


let baz = () => ({ });
jsApiThatShouldNeverAcceptTypeofFoo(baz)

let boo = () => { throw "Error" };
jsApiThatShouldNeverAcceptTypeofFoo(boo)

Upvotes: 1

Madara&#39;s Ghost
Madara&#39;s Ghost

Reputation: 174967

No, because a void returning function is assignable to a value returning function. On the other hand, you can't use the return value if you expected a void returning function. i.e.

let foo = () => 'foo';
let bar: () => void = foo; // produces no error

const result = bar(); // foo in runtime, TypeScript thinks it's void
const upper = result.toUpperCase(); // compile error

Upvotes: 1

Related Questions