#typescript #generics #types
#typescript #универсальные #типы
Вопрос:
Я хочу создать универсальную функцию, которая принимает асинхронную функцию, выполняет ее и улавливает ошибку, если предоставленная функция сталкивается с какими-либо проблемами.
поскольку я работаю на javascript, я смог создать следующую функцию, которая делает именно это. но я хотел улучшить ее с помощью дженериков и не смог этого сделать
этот код работает так, как ожидалось. но я не получаю никакого типа в своем аргументе ‘msg’.
const botAsyncHandler = (fn:Function) => (msg: any) => {
Promise.resolve(fn(msg)).catch(error => {
console.log(error.message);
});
};
итак, я попытался написать следующее
const botAsyncHandler = <T extends any>(fn:Function)=> (msg: T) => {
Promise.resolve(fn(msg)).catch(error => {
console.log(error.message);
console.log('here');
});
};
к сожалению, мой код не работает, и IDE по-прежнему сообщает мне, что сообщение имеет тип any неявно в следующем коде
bot.on('photo', botAsyncHandler(async msg => {}))
(возвращает : Parameter 'msg' implicitly has an 'any' type.
)
но выделение botAsyncHandler
показывает следующее:
botAsyncHandler<TelegramBot.Message>(fn: Function): (msg: TelegramBot.Message) => void
Похоже, это то, что я хочу. Мне любопытно узнать, где я ошибаюсь
Комментарии:
1. Примечание о вашей реализации JavaScript: если вы знаете,
fn
естьasync
, нет смыслаPromise.resolve(fn(arg))
. Если вы не знаете,fn
естьasync
(например, это может быть, а может и не быть), вы не будете перехватывать ошибки из него таким образом, если он синхронный.2. @T.J.Crowder вся цель функции — перехватить отклонение обещаний и обработать их. Это всегда асинхронно. Promise.resolve(fn(arg)) был просто для согласованности. функция не должна ничего возвращать. итак, пустота
3. Согласованность с чем ?
4. @T.J.Crowder хорошая мысль. когда я писал это, функция всегда должна была возвращать обещание, и я хотел, чтобы код был понятным
Ответ №1:
Function
Тип бесполезен. Не используйте ее. Тип fn
параметра примерно такой: (msg: T) => Promise<void>
. Или вы можете решить принять синхронные функции, которые возвращают void
: (msg: T) => void | Promise<void>
.
Вы могли бы написать:
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>'
И я не могу протестировать, но ваш код должен работать так, как ожидалось:
bot.on('photo', botAsyncHandler(async msg => {}))
Ответ №2:
Из вашего примера использования:
bot.on('photo', botAsyncHandler(async msg => {}))
и, например, JavaScript, похоже, что вы пытаетесь создать функцию, которая будет возвращать функцию, которая при вызове вызывала бы оригинал, но обрабатывала ошибки из него. Самый простой способ сделать это — просто написать async
функцию с try
/ catch
в ней. Версия JavaScript:
const botAsyncHandler = (fn) => async (msg) => {
try {
await fn(msg);
} catch (error) {
console.log(error.message);
}
};
добавление к ней аннотаций типов с обобщениями:
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);
}
};
Это предполагает, что функция должна объявлять один формальный параметр. <a rel="noreferrer noopener nofollow" href="https:///www.typescriptlang.org/play/index.html#src=type AsyncHandler = (arg: T) => {};
const botAsyncHandler = (fn: AsyncHandler) => async (msg: T) => {
try {
fn(msg);
} catch (error) {
console.log(error.message);
}
};
botAsyncHandler((str:string) => str);
botAsyncHandler((n:number) => n);
botAsyncHandler(() => { }); // Fails because function requires argument» rel=»nofollow noreferrer»>Жить на игровой площадке.
Но я не уверен, что добавление параметра типа дает вам что-нибудь здесь, учитывая, что вы используете <T extends any>
.
Комментарии:
1. отлично. это работает. но другой ответ, похоже, имеет лучшие типизации
2. @Omid — Действительно. Если бы это был я, я бы просто предложил изменения, но….