TypeScript类方法校验方法实现问题:参数匹配与类内调用
解决方案
问题分析
- 函数参数未严格校验:TypeScript默认允许参数更少的函数赋值给参数更多的函数(因JavaScript支持忽略多余参数),导致原代码无法检测参数个数不匹配的错误。
- 类内部调用失败:原代码使用
this作为泛型约束目标,构造函数中this的类型未完全确定,引发泛型推断异常。
修正后的代码
// 提取类中所有方法名的工具类型 type ClassMethodNames<T> = keyof { [K in keyof T as T[K] extends (...args: any[]) => any ? K : never]: T[K] }; // 强制函数参数个数、类型与返回值完全匹配的工具类型 type StrictFunctionMatch<T extends (...args: any[]) => any> = <U extends (...args: any[]) => any>( U extends (...args: Parameters<T>) => ReturnType<T> ? Parameters<U>['length'] extends Parameters<T>['length'] ? U : never : never ); class M { val!: string; fnDat!: (str: string, num: number) => Date; fnNum!: (num: number) => number; fnStr!: (str: string) => string; // 修正泛型约束,基于类原型确保类型推断准确 cheker<MethodName extends ClassMethodNames<typeof M.prototype>>( methodName: MethodName, method: StrictFunctionMatch<typeof M.prototype[MethodName]> ) { console.log(methodName, method); } constructor() { // 合法调用,无类型错误 this.cheker("fnDat", (str: string, num: number) => new Date()); this.cheker("fnNum", (num: number) => num); this.cheker("fnStr", (str: string) => str); // 以下调用均会触发类型错误,符合预期 this.cheker("val", () => {}); // 错误:val不是方法 this.cheker("fnDat", () => new Date()); // 错误:参数个数不匹配 this.cheker("fnDat", (str: string, num: number) => null); // 错误:返回类型应为Date this.cheker("fnNum", (num: number) => ""); // 错误:返回类型应为number this.cheker("fnStr", (str: string) => 10); // 错误:返回类型应为string this.cheker("fnNotExistsInM", () => {}); // 错误:方法名不存在 } } const m = new M(); // 外部合法调用 m.cheker("fnDat", (str: string, num: number) => new Date()); m.cheker("fnNum", (num: number) => num); m.cheker("fnStr", (str: string) => str); // 外部错误调用(均触发类型错误) m.cheker("val", () => {}); m.cheker("fnDat", () => new Date()); m.cheker("fnDat", (str: string, num: number) => null); m.cheker("fnNum", (num: number) => ""); m.cheker("fnStr", (str: string) => 10); m.cheker("fnNotExistsInM", () => {});
关键改动说明
ClassMethodNames优化:使用映射类型的as子句直接过滤出方法名,类型推导更简洁准确。StrictFunctionMatch工具类型:通过检查参数元组长度、参数类型和返回值类型,强制传入函数与目标方法完全匹配,解决参数个数不校验的问题。- 泛型约束调整:将泛型约束改为基于
typeof M.prototype,确保构造函数内this.cheker的类型推断正常工作。
内容的提问来源于stack exchange,提问作者Daniel de Andrade Varela
相关产品推荐
相关产品推荐

