Reputation: 448
I want to create a generic function that accepts an async function, executes it and catches the error if the provided function encounters any problems.
since I come from a javascript background, I was able to create the following function that does just that. but I wanted to improve it using generics and failed to do so
this code works as expected. but i don't get any type on my 'msg' argument.
const botAsyncHandler = (fn:Function) => (msg: any) => {
Promise.resolve(fn(msg)).catch(error => {
console.log(error.message);
});
};
so i tried to write the following
const botAsyncHandler = <T extends any>(fn:Function)=> (msg: T) => {
Promise.resolve(fn(msg)).catch(error => {
console.log(error.message);
console.log('here');
});
};
sadly my code does not work, and IDE still tells me that msg is of type any implicitly on the following code
bot.on('photo', botAsyncHandler(async msg => {}))
( returns : Parameter 'msg' implicitly has an 'any' type.
)
but highlighting the botAsyncHandler
shows the following:
botAsyncHandler<TelegramBot.Message>(fn: Function): (msg: TelegramBot.Message) => void
Which seems like what I want. I curious to know where I'm going wrong
Upvotes: 2
Views: 8299
Reputation: 1075249
From your example usage:
bot.on('photo', botAsyncHandler(async msg => {}))
and JavaScript example, it looks like you're trying to create a function that will return a function, which when called would call the original but handling errors from it. The simplest way to do that is just to write an async
function with a try
/catch
in it. JavaScript version:
const botAsyncHandler = (fn) => async (msg) => {
try {
await fn(msg);
} catch (error) {
console.log(error.message);
}
};
adding type annotations w/generics to it:
type AsyncHandler<T> = (arg: T) => {};
const botAsyncHandler = <T extends any>(fn: AsyncHandler<T>) => async (msg: T) => {
try {
await fn(msg);
} catch (error) {
console.log(error.message);
}
};
That assumes the function must declare one formal parameter. Live on the playground.
But I'm not sure adding a type parameter buys you anything here, given you're using <T extends any>
.
Upvotes: 1
Reputation: 23752
The Function
type is useless. Do not use it. The type of the fn
parameter is something like: (msg: T) => Promise<void>
. Or you can decide to accept synchronous functions that returns void
: (msg: T) => void | Promise<void>
.
You could write:
const botAsyncHandler = <T>(fn: (msg: T) => void | Promise<void>) => async (msg: T) => {
try {
await fn(msg);
} catch (err) {
console.log(err.message);
}
};
const onString = (msg: string) => {};
const fn = botAsyncHandler(onString);
// Here, the type of 'fn' is: '(msg: string) => Promise<void>'
And I can't test but your code should work as expected:
bot.on('photo', botAsyncHandler(async msg => {}))
Upvotes: 3