如何在TypeScript中为类方法的Contract集合保留类型信息
问题描述
我有一个用于定义函数契约的Contract类:
type MethodType = (...args: any) => any; class Contract<T extends MethodType> { }
我想创建一个针对类的契约管理类,尝试实现了ContractForClass:
class ContractForClass<T extends Record<string, any>> { methods!: Record<string, Contract<MethodType>>; forMethod(methodName: string): Contract<MethodType> { return this.methods[methodName] } setContractForMethod(method: string, contract: Contract<MethodType>) { this.methods[method] = contract } }
但当前存在类型信息丢失的问题:为类方法设置契约后,获取到的契约无法保留原始方法的类型。示例中:
const classContract = new ContractForClass<HttpClient<number>>(); classContract.setContractForMethod("get", new Contract<HttpClient<number>["get"]>) classContract.setContractForMethod("post", new Contract<HttpClient<number>["post"]>) const getcontract = classContract.forMethod("get")// 期望类型为Contract<(url: string) => number > const postContract = classContract.forMethod("post")// 期望类型为Contract<(url:string, payload: number) => void>
解决方案
要保留方法的类型信息,需要让ContractForClass的泛型精确映射类的方法类型,同时约束相关方法的类型匹配。修改后的代码如下:
type MethodType = (...args: any) => any; class Contract<T extends MethodType> { } // 过滤出类中的所有方法类型(排除非函数属性) type ClassMethods<T> = { [K in keyof T as T[K] extends MethodType ? K : never]: T[K] }; class ContractForClass<T extends Record<string, any>> { // 约束methods为类方法对应的Contract映射 methods!: { [K in keyof ClassMethods<T>]: Contract<ClassMethods<T>[K]> }; // 根据方法名返回对应类型的Contract forMethod<K extends keyof ClassMethods<T>>(methodName: K): Contract<ClassMethods<T>[K]> { return this.methods[methodName]; } // 确保方法名和传入的契约类型严格匹配 setContractForMethod<K extends keyof ClassMethods<T>>( method: K, contract: Contract<ClassMethods<T>[K]> ) { this.methods[method] = contract; } } // 示例用HttpClient类 class HttpClient<T> { get(url: string): number { return 1 as unknown as T; } post(url: string, payload: T): void {} } // 测试验证 const classContract = new ContractForClass<HttpClient<number>>(); classContract.setContractForMethod("get", new Contract<HttpClient<number>["get"]>()) classContract.setContractForMethod("post", new Contract<HttpClient<number>["post"]>()) const getContract = classContract.forMethod("get"); // 类型为Contract<(url: string) => number> const postContract = classContract.forMethod("post"); // 类型为Contract<(url: string, payload: number) => void>
核心改进点
ClassMethods<T>工具类型:自动过滤出类的方法属性,只保留函数类型的成员,避免非方法属性干扰。- 强类型约束的
methods:让每个方法名对应的契约类型与原方法完全一致,从根源上保留类型信息。 - 泛型方法
forMethod和setContractForMethod:通过泛型参数K约束方法名必须是类方法的有效键,同时让TypeScript自动推断对应的契约类型,确保类型安全。
内容的提问来源于stack exchange,提问作者Árpád Magosányi
相关产品推荐
相关产品推荐

