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

TypeScript调用签名技术求助:编译与运行结果矛盾

TypeScript调用签名实现问题解析与修复

问题根源分析

  1. 第一个场景:运行报错logFunc is not a function
    你定义的LogFunctionWithPrefixCB是一个带属性的函数类型,要求值本身是可调用的函数,同时拥有logPrefix属性。但你返回的ret是普通对象,只是通过类型断言as LogFunctionWithPrefixCB让TS认为它符合类型,但JS运行时里普通对象无法直接作为函数调用,因此触发错误。

  2. 第二个场景:编译报错Expected 2 arguments, but got 1
    你调用logFunc.call("hello world")时,TS识别的call是标准Function.prototype.call方法,它要求第一个参数是绑定的this,第二个才是函数参数。虽然你的自定义对象上有call方法,但TS并没有将其纳入类型检查,而是沿用标准函数的call签名,因此提示参数数量不足。

正确实现方式

要满足带属性的函数类型,必须创建一个函数对象,再给它添加额外属性,而不是用普通对象模拟。以下是几种可行的写法:

写法一:先创建函数再添加属性

type LogFunctionWithPrefixCB = {
    logPrefix: string;
    (stringToLog: string): void;
}

function makeLogFunctionWithPrefixCB(prefixStr: string): LogFunctionWithPrefixCB {
    // 定义基础函数
    const loggerFunc = function(stringToLog: string) {
        console.log(`${this.logPrefix}: ${stringToLog}`);
    };

    // 断言为目标类型并添加属性
    const logger = loggerFunc as LogFunctionWithPrefixCB;
    logger.logPrefix = prefixStr;

    return logger;
}

// 使用示例
function doSomething(logFunc: LogFunctionWithPrefixCB) {
    logFunc("hello world"); // 编译、运行均正常
}

const logger = makeLogFunctionWithPrefixCB("prefix:");
doSomething(logger);

写法二:用Object.assign合并函数与属性

type LogFunctionWithPrefixCB = {
    logPrefix: string;
    (stringToLog: string): void;
}

function makeLogFunctionWithPrefixCB(prefixStr: string): LogFunctionWithPrefixCB {
    return Object.assign(
        function(stringToLog: string) {
            console.log(`${this.logPrefix}: ${stringToLog}`);
        },
        { logPrefix: prefixStr }
    ) as LogFunctionWithPrefixCB;
}

写法三:箭头函数版本(词法作用域绑定)

如果不想依赖this,可以用箭头函数直接引用自身属性:

type LogFunctionWithPrefixCB = {
    logPrefix: string;
    (stringToLog: string): void;
}

function makeLogFunctionWithPrefixCB(prefixStr: string): LogFunctionWithPrefixCB {
    const logger = ((stringToLog: string) => {
        console.log(`${logger.logPrefix}: ${stringToLog}`);
    }) as LogFunctionWithPrefixCB;
    logger.logPrefix = prefixStr;
    return logger;
}

以上写法都能让返回值同时满足“可调用”和“拥有logPrefix属性”的要求,编译和运行阶段都不会出现错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 01:55:34