如何为基类exec方法添加强类型,使其仅接受派生类实例方法名?
限制基类方法仅接受派生类的实例方法名称
我们可以通过自定义类型工具结合this类型,实现基类方法仅接受派生类实例方法名称的强类型约束,以下是完整解决方案:
// 自定义类型工具:提取对象类型中所有值为函数的键 type MethodKeys<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T]; abstract class Animal { abstract species: string; breathe() { console.log(`Ahh`); } // 使用MethodKeys<this>限定参数仅为当前实例的方法名称 exec(methodName: MethodKeys<this>) { (this[methodName] as () => void)(); } } class Cat extends Animal { lovesCatnip = true; species = `felis catus`; meow() { console.log(`Meow`); } } class Dog extends Animal { chasesCars = true; species = `canis familiaris`; bark() { console.log(`Woof`); } } const fido = new Dog(); fido.exec(`breathe`); // ✅ 正常通过类型检查 fido.exec(`bark`); // ✅ 正常通过类型检查 fido.exec(`species`); // ❌ 类型报错:"species"不属于方法名称类型 fido.exec(`chasesCars`); // ❌ 类型报错:"chasesCars"不属于方法名称类型 const snowball = new Cat(); snowball.exec(`breathe`); // ✅ 正常通过类型检查 snowball.exec(`meow`); // ✅ 正常通过类型检查 snowball.exec(`species`); // ❌ 类型报错 snowball.exec(`lovesCatnip`); // ❌ 类型报错
核心逻辑说明
MethodKeys<T>类型工具:通过映射类型遍历T的所有键,仅保留值为函数类型的键,最终生成该类型下所有方法名称的联合类型。this类型的动态推导:当派生类实例调用基类的exec方法时,TypeScript会自动将this推导为派生类的实例类型(如Dog或Cat),因此MethodKeys<this>会精准提取当前派生类的所有方法名称,自动排除普通属性。- 严格类型约束:相比直接使用
keyof this,这种方式从类型层面就限制了参数只能是方法名称,彻底避免传入属性名导致的运行时风险。
内容的提问来源于stack exchange,提问作者RobertAKARobin
相关产品推荐
相关产品推荐

