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

TypeScript中T与void联合类型引发装饰器类型不兼容问题求助

TypeScript装饰器类型兼容问题的替代解决方案

问题根源在于当前Test装饰器返回的方法类型(...args: any[]) => InstanceType<T> | void包含了void,但test2方法声明必须返回Message,导致类型不兼容。以下是几种无需修改test2返回类型的解决办法:

方案一:给装饰器添加函数重载

通过重载明确区分传参和不传参两种场景的返回类型,让TypeScript自动匹配对应类型:

class Message {
    value: string;
}

type Class = { new (...args: any[]): any };

// 重载1:不传type时,返回允许void的方法类型
function Test(): (
    target: object,
    key: string | symbol,
    descriptor: PropertyDescriptor
) => TypedPropertyDescriptor<(...args: any[]) => void> | void;

// 重载2:传type时,返回仅包含目标实例类型的方法类型
function Test<T extends Class>(type: T): (
    target: object,
    key: string | symbol,
    descriptor: PropertyDescriptor
) => TypedPropertyDescriptor<(...args: any[]) => InstanceType<T>> | void;

// 装饰器实现
function Test<T extends Class>(type?: T) {
    return (
        target: object,
        key: string | symbol,
        descriptor: PropertyDescriptor
    ): TypedPropertyDescriptor<
        (...args: any[]) => InstanceType<T> | void
    > | void => {
    };
}

class Controller {
    @Test()
    test(): void { }

    @Test(Message)
    test2(): Message {
        return {
            value: 'test2'
        }
    }
}

方案二:使用条件泛型动态推断返回类型

通过泛型条件判断,根据是否传入type参数自动生成对应的返回类型,无需手动写重载:

class Message {
    value: string;
}

type Class = { new (...args: any[]): any };

// 第二个泛型参数R根据T是否存在动态推断返回类型
function Test<T extends Class | undefined = undefined, R = T extends Class ? InstanceType<T> : void>(type?: T) {
    return (
        target: object,
        key: string | symbol,
        descriptor: PropertyDescriptor
    ): TypedPropertyDescriptor<(...args: any[]) => R> | void => {
    };
}

class Controller {
    @Test()
    test(): void { }

    @Test(Message)
    test2(): Message {
        return {
            value: 'test2'
        }
    }
}

方案三:适配原方法参数并精确控制返回类型

让装饰器兼容原方法的参数类型,同时根据type参数精确控制返回类型,提升类型严谨性:

class Message {
    value: string;
}

type Class = { new (...args: any[]): any };

// 用泛型M表示原方法的类型,保证参数匹配
function Test<T extends Class | undefined = undefined>(type?: T) {
    return <M extends (...args: any[]) => any>(
        target: object,
        key: string | symbol,
        descriptor: TypedPropertyDescriptor<M>
    ): TypedPropertyDescriptor<
        // 有type则返回目标实例类型,否则保留原方法返回类型
        T extends Class ? (...args: Parameters<M>) => InstanceType<T> : M
    > | void => {
    };
}

class Controller {
    @Test()
    test(): void { }

    @Test(Message)
    test2(): Message {
        return {
            value: 'test2'
        }
    }
}

内容的提问来源于stack exchange,提问作者George Hulpoi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:07:49