You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 19:24:58