如何修正TypeScript中EventObject泛型与inputSchema不匹配无报错问题?
解决Zod EventObject类型不校验inputSchema匹配问题
问题描述
用Zod实现WebSocket命令输入验证,拆分到多文件中,定义了如下泛型类型:
export type EventObject<T> = { name: string; inputSchema: T; callback(input: T): any; };
但手动使用类型断言声明对象时,即使inputSchema的类型与泛型指定的不匹配,TypeScript也不会报错:
const schema = z.object({}); const schema2 = z.object({ test: z.string() }); export default { name: "create", inputSchema: schema2, callback(args) {} } as EventObject<typeof schema>; // 此处未触发类型不匹配报错,不符合预期
解决方案
核心问题是手动类型断言会跳过TypeScript的结构校验,改用类型约束的工厂函数来创建EventObject,让TypeScript自动推断并校验一致性:
1. 优化类型定义(可选但更实用)
调整EventObject的callback参数类型,让它对应Zod Schema解析后的实际业务数据类型,而非Schema本身:
import { z } from "zod"; export type EventObject<T extends z.ZodTypeAny> = { name: string; inputSchema: T; callback(input: z.infer<T>): any; // z.infer<T>获取Schema对应的业务数据类型 };
2. 创建工厂函数约束类型
通过工厂函数强制校验传入对象的结构与泛型类型的一致性:
export function createEvent<T extends z.ZodTypeAny>(event: EventObject<T>): EventObject<T> { return event; }
3. 正确使用方式
用工厂函数创建事件对象,TypeScript会自动推断泛型并校验inputSchema与整体类型的匹配性:
const schema = z.object({}); const schema2 = z.object({ test: z.string() }); // 正确示例:自动推断类型,callback参数自动关联Schema类型 export default createEvent({ name: "create", inputSchema: schema, callback(args) { // args类型为{},与schema解析后的类型一致 } }); // 错误示例:inputSchema与泛型不匹配时直接报错 export default createEvent({ name: "create", inputSchema: schema2, callback(args) {} } as EventObject<typeof schema>); // TypeScript会提示类型不兼容 // 推荐写法:无需手动指定泛型,写错inputSchema直接触发报错 export default createEvent({ name: "create", inputSchema: schema2, callback(args) { // args自动推断为{ test: string } } });
原理说明
原来的as EventObject<typeof schema>属于类型断言,会强制TypeScript认可对象的类型,跳过结构校验。而工厂函数通过接收EventObject<T>类型的参数,让TypeScript自动推断T的类型,并严格校验传入对象的每个属性是否符合EventObject<T>的结构,从而避免类型不匹配的问题。
内容的提问来源于stack exchange,提问作者kalempster
相关产品推荐
相关产品推荐

