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

TypeScript函数包装器类型兼容问题:如何消除类型报错?

TypeScript钩子注入函数的类型兼容问题解决

我用TypeScript重写旧浏览器扩展时,碰到一个用来包装函数实现「钩子注入」的工具函数。虽然生产环境会换掉它,但想写出能通过TypeScript类型检查的版本,目前代码报类型错误,以下是我写的最优版本:

type GetReturnType<Type> = Type extends (...args: never[]) => infer Return ? Return : never;
type GetArgsType<Type> = Type extends (...args: infer Args) => any ? Args : never

export function wrapFunction<T, K extends keyof T>(
    parent: T,
    name: K,
    newFunction: (
        oldFn: T[K],
        ...args: GetArgsType<T[K]>
    ) => GetReturnType<T[K]>
) {
    var oldFunction = parent[name]
    parent[name] = (...args:GetArgsType<T[K]>) => {
        return newFunction(oldFunction, ...args)
    }
    return parent[name]
}

TypeScript引擎在parent[name] = ...这一行抛出如下报错:

Type '(...args: GetArgsType<T[K]>) => GetReturnType<T[K]>' is not assignable to type 'T[K]'.
  'T[K]' could be instantiated with an arbitrary type which could be unrelated to '(...args: GetArgsType<T[K]>) => GetReturnType<T[K]>'.

解决方案

核心问题是原代码没有约束T[K]必须是函数类型,TypeScript无法确定T[K]一定和新函数的类型兼容。我们可以通过泛型约束缩小范围,结合TypeScript内置的类型工具来修复:

// 提取对象中值为函数类型的键
type FunctionKeys<T> = { [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never }[keyof T]

export function wrapFunction<T, K extends FunctionKeys<T>>(
    parent: T,
    name: K,
    newFunction: (
        oldFn: T[K],
        ...args: Parameters<T[K]>
    ) => ReturnType<T[K]>
): T[K] {
    const oldFunction = parent[name]
    // 类型断言告知TypeScript新函数与T[K]类型兼容
    parent[name] = ((...args: Parameters<T[K]>) => {
        return newFunction(oldFunction, ...args)
    }) as T[K]
    return parent[name]
}

说明

  1. FunctionKeys<T>类型用来筛选出对象T中所有值为函数的键,确保K对应的属性一定是函数,避免了类型不确定的问题。
  2. 用TypeScript内置的Parameters<T>和ReturnType<T>替代自定义的GetArgsType和GetReturnType,更简洁且符合官方规范。
  3. 最后通过类型断言as T[K]让TypeScript确认新赋值的函数与原属性类型匹配,解决剩余的类型推导问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:33:30