TypeScript如何为参数符合指定接口的方法定义类型签名
错误原因
TypeScript的函数参数类型是逆变的:
- 你最初定义的
HandleCommandFn类型约定是:该函数可以接收任意实现了Command接口的参数 - 但你赋值的
handleHello只能接收HelloCommand这一种子类型的参数,无法兼容其他Command实现类的入参,自然不符合类型约定,编译器就会抛出不兼容的错误。
你之前尝试的两种泛型写法都把泛型声明放在了函数签名内部,相当于要求函数本身要支持调用时传入任意C extends Command的参数,本质还是要求函数适配所有Command子类,和最初的写法没区别,所以解决不了问题。
解决方案
把泛型参数提到类型定义的外层,让每个具体的处理函数可以绑定到特定的Command实现类:
// 泛型C定义在类型上,每个HandleCommandFn实例对应一种Command子类 type HandleCommandFn<C extends Command> = (command: C) => Promise<any>; // 声明时指定C为HelloCommand即可通过校验 const handleHello: HandleCommandFn<HelloCommand> = ( command: HelloCommand ): Promise<string> => { return Promise.resolve(`Hello ${command.name}`); };
类型安全装饰器实现说明
你最终的实现是正确的:
- 泛型
C同时挂载到HandleCommandFn类型和HandleCommand装饰器函数上 - 装饰器会自动推断被装饰方法的入参类型,校验入参是否实现了
Command接口、返回值是否为Promise - 不符合要求的方法会直接抛出编译错误,完全满足类型安全的需求。
内容的提问来源于stack exchange,提问作者Sylvain Desvé
相关产品推荐
相关产品推荐

