TypeScript仅能解析node-telegram-bot-api最后一个on重载的问题求助
解决node-telegram-bot-api中TelegramBot.on()重载的TypeScript类型推断问题
你遇到的问题根源是TypeScript处理重载函数类型时,默认只会用最后一个重载签名进行条件类型推断。你定义的Handler<T>类型中,TOnType extends (e:T, a: infer R) => void只会匹配on()的最后一个重载(对应'chat_join_request'的那个),所以只有当T是'chat_join_request'时能正确推断handler类型,其他event类型都会因为不匹配最后一个重载而导致推断失败。
方案一:手动创建事件-处理器映射类型(推荐)
手动定义一个映射类型,将每个event类型关联到对应的处理器参数类型,这种方式直观且可靠,不受库重载变化的影响(除非新增event类型,只需补充对应项即可):
import TelegramBot from 'node-telegram-bot-api'; // 定义事件到处理器参数的映射 type EventToHandler = { 'callback_query': TelegramBot.CallbackQuery; 'inline_query': TelegramBot.InlineQuery; 'poll_answer': TelegramBot.PollAnswer; 'chat_member': TelegramBot.ChatMemberUpdated; 'my_chat_member': TelegramBot.ChatMemberUpdated; 'chosen_inline_result': TelegramBot.ChosenInlineResult; 'channel_post': TelegramBot.Message; 'edited_message': TelegramBot.Message; 'edited_message_text': TelegramBot.Message; 'edited_message_caption': TelegramBot.Message; 'edited_channel_post': TelegramBot.Message; 'edited_channel_post_text': TelegramBot.Message; 'edited_channel_post_caption': TelegramBot.Message; 'shipping_query': TelegramBot.ShippingQuery; 'pre_checkout_query': TelegramBot.PreCheckoutQuery; 'polling_error': Error; 'webhook_error': Error; 'error': Error; 'chat_join_request': TelegramBot.ChatJoinRequest; }; // 生成对应事件的处理器类型 export type Handler<T extends keyof EventToHandler> = (payload: EventToHandler[T]) => void;
使用示例:
// 现在两种场景都能正确推断类型 const callbackHandler: Handler<'callback_query'> = (query) => { console.log(query.id); // 类型推断为TelegramBot.CallbackQuery }; const joinRequestHandler: Handler<'chat_join_request'> = (request) => { console.log(request.chat.id); // 类型推断为TelegramBot.ChatJoinRequest };
方案二:自动从重载中提取映射类型
如果你希望自动从on()的重载中提取类型(无需手动维护映射),可以通过类型推断将重载函数转换为联合类型,再提取事件与处理器的对应关系:
import TelegramBot from 'node-telegram-bot-api'; // 将重载函数转换为所有重载的联合类型 type Overloads<T> = T extends { (...args: infer A1): infer R1; (...args: infer A2): infer R2; (...args: infer A3): infer R3; (...args: infer A4): infer R4; (...args: infer A5): infer R5; (...args: infer A6): infer R6; (...args: infer A7): infer R7; (...args: infer A8): infer R8; (...args: infer A9): infer R9; (...args: infer A10): infer R10; } ? ((...args: A1) => R1) | ((...args: A2) => R2) | ((...args: A3) => R3) | ((...args: A4) => R4) | ((...args: A5) => R5) | ((...args: A6) => R6) | ((...args: A7) => R7) | ((...args: A8) => R8) | ((...args: A9) => R9) | ((...args: A10) => R10) : never; // 提取on()的所有重载 type OnFunctionOverloads = Overloads<TelegramBot['on']>; // 提取每个重载的事件和处理器类型对 type EventHandlerPair = OnFunctionOverloads extends (...args: [infer E, infer H]) => any ? [E, H] : never; // 生成自动映射类型 type EventToHandlerAuto = { [K in EventHandlerPair[0]]: Extract<EventHandlerPair, [K, infer H]> extends [K, H] ? H extends (payload: infer P) => void ? P : never : never; }; // 生成处理器类型 export type HandlerAuto<T extends keyof EventToHandlerAuto> = EventToHandlerAuto[T];
使用示例:
const inlineHandler: HandlerAuto<'inline_query'> = (query) => { console.log(query.query); // 类型推断为TelegramBot.InlineQuery }; const errorHandler: HandlerAuto<'error'> = (err) => { console.error(err.message); // 类型推断为Error };
说明:这种方式需要根据on()的重载数量调整Overloads类型的参数数量,如果后续库更新增加了重载,需要同步修改Overloads的定义,因此不如手动映射稳定。
内容的提问来源于stack exchange,提问作者Горбачев ес чо
相关产品推荐
相关产品推荐

