TypeScript中Telegram机器人消息常量的类型Schema优化问题
问题描述
我正在开发一个Telegram机器人,希望将所有消息存储为常量。现有消息类型Schema如下:
type MessagesSchema = { [K in keyof typeof MessagesEnum]: string }
其实现代码为:
const Messages: MessagesSchema = { SOME_KEYS_FROM_ENUM: '123', // ... FUNCTIONAL_VALUE: (a: number) => `The number is ${a}` }
目前无法直接在该常量中设置函数类型的值,我曾尝试将Schema改写为:
type MessagesSchema = { [K in keyof typeof MessagesEnum]: string | ((...params: any) => string) }
但这样每次使用值时都需要判断是否可调用:
if(typeof Messages.FUNCTIONAL_VALUE === 'function'){ // ... }
请问如何改写Schema才能正确使用函数类型的值,同时避免每次的类型判断?
解决方案
方法1:为枚举成员映射明确的类型
通过枚举与类型的精准映射,让每个枚举键对应固定的类型(字符串或特定签名的函数),TypeScript会直接推断出每个键的类型,无需额外判断。
示例代码:
// 定义消息枚举 enum MessagesEnum { StaticText = 'StaticText', DynamicNumber = 'DynamicNumber' } // 为每个枚举成员定义对应类型 type MessagesSchema = { [MessagesEnum.StaticText]: string; [MessagesEnum.DynamicNumber]: (num: number) => string; } // 实现常量时,TypeScript会严格校验每个键的类型 const Messages: MessagesSchema = { [MessagesEnum.StaticText]: '固定文本内容', [MessagesEnum.DynamicNumber]: (a: number) => `The number is ${a}` } // 使用时直接调用,无需类型判断 const result = Messages.DynamicNumber(123); // 类型推断正确,直接使用
方法2:利用TypeScript类型推断自动推导
如果不想手动维护每个键的类型,可以让TypeScript根据Messages常量的实际值自动推导类型,再结合枚举约束键的范围。
示例代码:
enum MessagesEnum { SOME_KEYS_FROM_ENUM, FUNCTIONAL_VALUE } // 先定义常量,让TS自动推导类型 const Messages = { [MessagesEnum.SOME_KEYS_FROM_ENUM]: '123', [MessagesEnum.FUNCTIONAL_VALUE]: (a: number) => `The number is ${a}` } as const; // 基于枚举和常量推导Schema类型 type MessagesSchema = { [K in keyof typeof MessagesEnum]: typeof Messages[K] } // 使用时直接调用,类型完全匹配 Messages.FUNCTIONAL_VALUE(456); // 无需判断,TS直接识别为函数类型
方法3:拆分枚举区分静态/动态消息
如果需要批量区分静态字符串和动态函数,可以拆分枚举并分别定义类型,再合并为完整的消息Schema:
enum StaticMessagesEnum { GREETING = 'GREETING', HELP_TEXT = 'HELP_TEXT' } enum DynamicMessagesEnum { USER_INFO = 'USER_INFO', ORDER_STATUS = 'ORDER_STATUS' } type StaticMessages = { [K in StaticMessagesEnum]: string }; type DynamicMessages = { [K in DynamicMessagesEnum]: (...args: any[]) => string }; // 合并为完整的消息类型 type MessagesSchema = StaticMessages & DynamicMessages; const Messages: MessagesSchema = { [StaticMessagesEnum.GREETING]: '欢迎使用机器人!', [StaticMessagesEnum.HELP_TEXT]: '发送/help获取帮助', [DynamicMessagesEnum.USER_INFO]: (name: string, age: number) => `用户${name},年龄${age}`, [DynamicMessagesEnum.ORDER_STATUS]: (status: string) => `订单状态:${status}` } // 使用时直接调用对应类型 Messages.USER_INFO('张三', 25); // 类型校验通过,无需判断
内容的提问来源于stack exchange,提问作者xoma_star
相关产品推荐
相关产品推荐

