如何移除TypeScript多调用签名接口中的指定调用签名
问题原因
之前用Exclude失败的根本原因有两点:
- 多调用签名的接口是重载函数类型,不是联合类型,而
Exclude是专门用来过滤联合类型成员的工具,本身不支持重载签名的细粒度剔除。 - 直接对整个重载接口做类型匹配时,TS会判定整个重载类型可赋值给你传入的待排除单签名,最终
Exclude直接返回never,其余签名完全丢失。
正确实现方案
核心思路是利用TS对重载函数做条件类型推断时,会逐个遍历调用签名分发处理的特性,先过滤掉需要替换的旧签名,再交叉合并新签名即可。
通用签名过滤实现
先定义通用的重载调用签名过滤工具类型:
type RemoveCallSignature<T, TargetSignature> = T extends (...args: infer Args) => infer Return ? TargetSignature extends (...args: Args) => infer TargetReturn ? Return extends TargetReturn ? Args extends Parameters<TargetSignature> ? never : (...args: Args) => Return : (...args: Args) => Return : (...args: Args) => Return : never;
使用方式:
// 1. 剔除旧的authorize调用签名 type FilteredBase = RemoveCallSignature<Foo, (options: {method: 'authorize', userId: number}) => Promise<string>>; // 2. 合并新签名,得到最终的Bar类型 type Bar = FilteredBase & ((options: {method: 'authorize', userToken: string}) => Promise<string>);
场景化简化实现
如果你的重载签名都是以{method: 字面量类型}作为入参格式,可以写更简洁的按method值过滤的工具类型,避免通用类型比对的边缘兼容问题:
type RemoveSignatureByMethod<T, MethodType extends string> = T extends (options: infer Options) => infer Return ? Options extends {method: MethodType} ? never : (options: Options) => Return : never; // 使用 type FilteredBase2 = RemoveSignatureByMethod<Foo, 'authorize'>; type Bar2 = FilteredBase2 & ((options: {method: 'authorize', userToken: string}) => Promise<string>);
效果验证
declare const bar: Bar; // 新authorize签名正常,要求传userToken bar({method: 'authorize', userToken: 'test_token'}); // 类型校验通过 // 旧authorize签名已被移除,传userId会报错 // bar({method: 'authorize', userId: 123}); // 类型报错 // deauthorize签名完整保留 bar({method: 'deauthorize', authToken: 'test_auth'}); // 类型校验通过
内容的提问来源于stack exchange,提问作者steveluscher
相关产品推荐
相关产品推荐

