I mean it should return undefined
or no return at all. Typical for safe callbacks.
Tryout 1:
declare const fn1: (cb: () => void) => void;
fn1(() => '123'); // no error
Oops. It didn't work out. string
is applicable to void
. Ok...
Tryout 2:
declare const fn2: (cb: () => unknown) => void;
fn2(() => '123'); // no error
Oops. The same. Ooookay.
Tryout 3:
declare const fn3: (cb: () => undefined) => void;
fn3(() => '123'); // error: Type 'string' is not assignable to type 'undefined'
Nice, Ok: go with it:
fn3(() => undefined); // okay
fn3(() => {}); // error: Type 'void' is not assignable to type 'undefined'
Hm. It's not what I'm looking for.
Okay, what's about this crazy idea? Tryout 4:
declare const fn4: (cb: () => void | undefined) => void;
fn4(() => undefined); // okay
fn4(() => { }); // okay
fn4(() => '123'); // error: Type 'string' is not assignable to type 'undefined'
Wow. It's what I wanted.
But it looks like a dirty hack. Why on the Earth void
doesn't complain about string
, but void | undefined
void | undefined
does it? Is it a bug?
Can I rely on this behavior? Wouldn't it be fixed in some future versions of TS? Is there any better way to accomplish the same?
UPDATED 2
a callback that shouldn't have any args even optional and shouldn't return anything should be defined like that:
type callback = (...a: void[]) => void | undefined;
const func = (a: callback) => {
a();
};
const test1 = func(() => { }); // works
const test2 = func((a?: string) => { }); // fails
const test2 = func(() => '5'); // fails
UPDATED
after discussion in comments was found out that the goal is to get a callback not with ignored return, but with guarantee that it won't return anything else and it can be passed to other functions that change behavior based on returned value.
In this case I would suggest to add a small helper function that really ignores any returned value.
const shutUp = <T extends (...args: any) => void>(func: T): ((...args: Parameters<T>) => void) => (...args: any[]) => {
func(...args);
};
const shutUpNoArgs = <T extends () => void>(func: T): ((...args: never) => void) => () => {
func();
};
const test = shutUp((a: string) => 5);
const r1 = test('5'); // works, r1 is void.
const r2 = test(5); // doesn't work.
_.forEach(data, shutUp(callback));
ORIGINAL
You shouldn't be so strict and to worry too much about that.
void
means we don't care about return, should we if we don't rely on it?
It's the same as to say that we don't accept a function because it doesn't require our a
argument despite it can handle the case.
declare const fn1: (cb: (a: string) => void) => void;
fn1(() => {
}); // no error even we don't have `a` in our callback.
Docs: https://www.typescriptlang.org/docs/handbook/basic-types.html#void
void
is a little like the opposite ofany
: the absence of having any type at all.
Therefore, its behavior won't be changed you can use it in a union with undefined
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.