TypeScript能否通过泛型根据一个参数的类型约束另一个回调参数的类型?
问题根因
当前泛型校验失效是两个TypeScript特性共同导致的:
- 泛型推断默认会收集所有入参位置的类型做推导:你同时给第一个参数传了
AwesomeEventType、第二个参数的回调标了DifferentEventType时,TS会尝试把泛型T推导为两者的兼容父类型或者联合类型,只要结构匹配就不会报错。 - 未开启
strictFunctionTypes时,TS对函数参数采用双向协变校验:允许子类参数赋值给父类参数的同时,也允许父类参数赋值给子类参数,只要结构兼容就不会触发类型错误。
解决方案
方案1:开启严格函数类型校验(推荐)
在tsconfig.json的compilerOptions中开启strictFunctionTypes(如果已开启strict模式,该选项默认生效),开启后函数参数会采用严格的逆变校验,只要回调参数类型和事件类实例类型不匹配,就会直接抛出编译错误。
方案2:限制泛型推断来源(兼容非严格模式)
如果需要适配未开启严格模式的场景,可以通过NoInfer工具类型限制TS只能从第一个事件类参数推导泛型T,不会从回调参数反向推导:
// TypeScript 5.4及以上版本已内置NoInfer,低于该版本可以手动定义 type NoInfer<T> = [T][T extends any ? 0 : never]; // 修改后的方法定义 addEventListener<T>( eventType: { new (...args: any[]): T }, eventHandler: (event: NoInfer<T>) => void )
修改后泛型T的类型完全由第一个入参的事件类决定,回调参数如果不匹配T的类型就会触发编译错误。
内容的提问来源于stack exchange,提问作者spmealin
相关产品推荐
相关产品推荐

