【问题标题】:Argument of type 'Function' is not assignable to parameter of type '(...args: any[]) => void''Function' 类型的参数不可分配给 '(...args: any[]) => void' 类型的参数
【发布时间】:2018-08-08 10:55:23
【问题描述】:
function on(event: string, listener: Function) {
    console.log('on event: ', event, 'typeof listener:', typeof (listener));
    listener();
}

function on1(event: string, listener: (...args: any[]) => void) {
    console.log('on event: ', event, 'typeof listener:', typeof (listener));
    listener();
}

function createCallback(a: number): Function {
    let f = (a: number) => {
        console.log('return a:', a);
        return (a: number) => { return a + 1 };
    };
    return f(a);
}

let f = createCallback(1);
console.log('type of f', typeof (f));
// on("start", f);
on1("start", f);

在上面的代码中,on("start", f) 工作正常,但 on1("start", f); 返回错误

main.ts:22:14 - 错误 TS2345:'Function' 类型的参数不可分配给'(...args: any[]) => void' 类型的参数。 类型 'Function' 不匹配签名 '(...args: any[]): void'。 22 on1("开始", f); ~

如果我删除createCallbackFunction 类型断言,on1("start", f) 有效,Function 不是表示闭包的通用类型吗?

最初的问题来自这个提交,https://github.com/DefinitelyTyped/DefinitelyTyped/commit/96545154cc6488643a7064a6dc4ec9726c7af12a#diff-7d84e08967cded0b99ed4328aab0a1a8L291

我不明白他为什么将Function 更改为(...args: any[]) => void,这导致我的代码中断。

【问题讨论】:

  • “函数不是表示闭包的通用类型吗?” — 对,它是一个 general 类型,但您的函数 on1 需要更具体的类型。就像Any 是一个通用类型,不能绑定到更具体的类型(但它本身可以绑定任何东西)。

标签: typescript


【解决方案1】:

有一个suggestion 允许这样的事情,因为Function 可以分配给(...args: any[]) => any。这不是当前行为的原因是:

Function 的初衷是不可调用。换句话说,函数到函数类型应该像其他类型一样未知,但不可调用。我们已经放宽了这个限制,通过特殊的大小写在编译器中赋予 Function 一个可调用的行为。我们已经讨论过将其设为 --noImplicitAny 错误,因为调用函数确实不安全。

如果这对您很重要,我建议您投票赞成该建议。

我通常会远离Function,它不是一种类型安全的方法来表达函数签名。对于您的情况,我将使用以下内容:

function on(event: string, listener: (...args: any[]) => void) {
    console.log('on event: ', event, 'typeof listener:', typeof (listener));
    listener();
}

function createCallback(a: number)  { // we can omit the return type or be explicit and type it as (a: number) => number
    let f = (a: number) => {
        console.log('return a:', a);
        return (a: number) => { return a + 1 };
    };
    return f(a);
}

let f = createCallback(1); // (a: number) => number 
on("start", f);

【讨论】:

  • @xcaptain 添加了一个示例,其中包含我将为您做的用例,您可以在 createCallback 的返回类型中显式编写函数类型,或者您可以让编译器推断它。
  • 谢谢我明白了,我在这里创建了一个更复杂的例子gist.github.com/xcaptain/…,你认为如果返回一个闭包,不要指定返回类型是个好主意,因为(...args: any[]) => void就像什么都没说。
  • @xcaptain 在调用站点有或没有显式返回类型,您将得到相同的错误和代码完成。显式返回类型将添加的唯一内容是验证您从create* 函数内部返回正确值。由您决定这是否值得您为复杂的返回类型输入的长度类型。
猜你喜欢
  • 2019-09-06
  • 2021-08-24
  • 2023-04-05
  • 1970-01-01
  • 2022-01-05
  • 2021-10-22
  • 2022-01-17
  • 2021-08-11
  • 1970-01-01
相关资源
最近更新 更多