如何在TypeScript中强制对象类型仅包含字符串键?
解决TypeScript中强制对象类型仅含字符串键并修复模板字符串报错问题
问题分析
你的代码中StrKeyObj仅将非字符串键对应的值设为never,但并未真正排除symbol或number类型的键。keyof Models仍可能包含symbol类型,而模板字符串${keyof Models}.${Method}要求拼接项必须是字符串类型,因此触发报错。
解决方案
方案1:约束对象仅允许字符串键(彻底禁止非字符串键)
定义工具类型明确禁止number和symbol类型的键,确保keyof Models仅为字符串:
// 仅允许字符串键的对象类型,禁止number/symbol键 type StringKeyedObj<T = any> = { [K in string]: T; } & { [K in number | symbol]: never; }; export interface EventHandler< Method extends 'create' | 'update', Models extends StringKeyedObj = StringKeyedObj > { on: `${keyof Models}.${Method}`; // 此时keyof Models仅为string,无报错 main(): void; }
验证:
- 传入含非字符串键的对象会触发约束报错:
const testSym = Symbol('demo'); type InvalidModel = { [testSym]: number; name: string }; // 报错:类型“InvalidModel”不满足约束“StringKeyedObj<any>” type BadHandler = EventHandler<'create', InvalidModel>; - 传入合法字符串键对象正常工作:
type ValidModel = { user: string; post: number }; type GoodHandler = EventHandler<'update', ValidModel>; // on的类型为 "user.update" | "post.update",符合预期
方案2:过滤非字符串键(兼容数字键转为字符串的场景)
如果允许对象存在数字键(TypeScript会自动将数字键转为字符串),仅需在模板字符串中提取字符串类型的键:
export interface EventHandler< Method extends 'create' | 'update', Models extends Record<string, any> = Record<string, any> > { on: `${Extract<keyof Models, string>}.${Method}`; main(): void; }
说明:Extract<keyof Models, string>会从keyof Models中过滤出仅字符串类型的键,确保模板字符串拼接合法。
内容的提问来源于stack exchange,提问作者TOPKAT
相关产品推荐
相关产品推荐

