TypeScript中如何禁止接口的函数类型属性被实现为类方法?
解决方案
可以通过调整接口定义的方式,触发编译报错禁止普通方法实现该接口,核心是利用函数参数逆变、方法参数双变的类型差异,加入严格的逆变校验约束即可。
实现方式1:给泛型参数添加逆变标记
这是最简单的实现方案,只需要给接口的输入泛型I加上逆变标记in:
interface MyInterface<in I, O> { execute: (input: I) => O }
校验效果验证
- 箭头函数属性实现:编译正常通过,符合预期
class MyClassArrow implements MyInterface<string, number> { execute = (input: string): number => 1; }
- 普通类方法实现:触发编译报错,符合预期
class MyClassMethod implements MyInterface<string, number> { // TS 类型报错:方法的双变参数特性不满足泛型逆变约束 execute(input: string): number { return 1; } }
实现方式2:通过条件类型强制校验函数类型
如果不想修改原接口的泛型声明,可以通过条件类型封装严格函数校验逻辑,过滤掉双变的方法类型:
// 严格函数校验工具类型,仅接受逆变特性的函数类型,排除双变的方法类型 type StrictFunction<F extends (...args: any[]) => any> = F extends (...args: infer A) => infer R ? ((x: (...args: A) => R) => void) extends ((x: F) => void) ? F : never : never // 原接口仅需要修改execute的类型定义 interface MyInterface<I, O> { execute: StrictFunction<(input: I) => O> }
该方案的校验效果和方案1完全一致。
原理说明
- 未加约束时,TS允许双变的方法类型兼容逆变的函数字面量类型,因此两种实现都能通过校验
- 加入逆变约束后,仅参数为逆变的函数字面量(即箭头函数属性实现)满足要求
- 普通类方法的参数为双变,无法通过严格的逆变类型校验,因此会触发编译报错
内容的提问来源于stack exchange,提问作者james
相关产品推荐
相关产品推荐

