如何让实例方法仅接受另一个实例方法的名称?
解决方法
你可以通过TypeScript的条件类型提取类中仅为方法的属性名,再排除command自身,就能实现需求。直接看修改后的代码:
type MethodKeys<T> = { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]; class User { nameFirst: string; nameLast: string; command(commandName: Exclude<MethodKeys<this>, 'command'>) { (this[commandName] as Function).call(this); } sink() { console.log('sinking'); } swim() { console.log('swimming'); } } const alice = new User(); alice.command('swim'); // ✅ 合法 alice.command('sink'); // ✅ 合法 alice.command('nameFirst'); // ❌ 报错,不是方法 alice.command('command'); // ❌ 报错,排除了自身
关键部分解释
MethodKeys<T>类型:- 遍历
T的所有键K,判断T[K]是否为函数类型。如果是则保留键名K,否则返回never。 - 最后通过
[keyof T]索引访问,自动过滤掉所有never类型,只留下方法名组成的联合类型。
- 遍历
Exclude<MethodKeys<this>, 'command'>:- 用
Exclude从方法名联合类型中剔除command自身,避免出现command('command')这种无意义的递归调用。
- 用
类型断言
as Function:- 虽然我们已经通过类型约束保证了
commandName对应的是方法,但TypeScript编译器无法完全自动推断,加个断言就能让代码通过检查。
- 虽然我们已经通过类型约束保证了
这样修改后,command方法只会接受类中的普通方法名,后续新增方法也会自动被纳入允许范围,完全不需要硬编码方法列表。
内容的提问来源于stack exchange,提问作者RobertAKARobin
相关产品推荐
相关产品推荐

