【问题标题】:Error: Cannot invoke an expression whose type lacks a call signature错误:无法调用类型缺少调用签名的表达式
【发布时间】:2017-02-03 03:37:22
【问题描述】:

我是打字稿的新手,我有两门课。在我的父类中:

abstract class Component {
  public deps: any = {};
  public props: any = {};

  public setProp(prop: string): any {
    return <T>(val: T): T => {
      this.props[prop] = val;
      return val;
    };
  }
}

在我的子类中:

class Post extends Component {
  public toggleBody: string;

  constructor() {
    this.toggleBody = this.setProp('showFullBody');
  }

  public showMore(): boolean {
    return this.toggleBody(true);
  }

  public showLess(): boolean {
    return this.toggleBody(false);
  }
}

showMore 和 ShowLess 都给我错误,“无法调用类型缺少调用签名的表达式。”

但是我认为 setProp 返回的函数确实有调用签名?我想我误解了关于函数类型的重要内容,但我不知道它是什么。

谢谢!

【问题讨论】:

  • togglrBody 不应该是一个字符串,因为你希望它是一个函数
  • @eavidan 是的,它是一个实际返回布尔值的函数。我原本以为它会返回一个字符串。那我该怎么改呢?
  • 无论 setProp 返回什么,看起来像 &lt;T&gt;(val: T) =&gt; T

标签: javascript angularjs typescript types


【解决方案1】:

它返回的函数有一个调用签名,但你告诉 Typescript 通过在其签名中添加 : any 来完全忽略它。

【讨论】:

  • 好的进展,谢谢!现在我得到“错误 TS2322:类型 '(val: T) => T' 不可分配给类型 'boolean'。”如果我删除:any。我认为这就是我首先添加 :any 的原因。我实际上仍然得到原始错误。
  • 如果我这样做并将public toggleBody: boolean; 更改为public toggleBody: any; 它可以工作。
  • @Justin 为什么你还期待别的?您声称this.toggleBody 应该返回boolean,但这与您分配给它的setProp 的返回值不一致。您似乎只是随意地输入类型,而没有考虑您真正想要发送和返回的内容。
  • @jonrsharpe 好的,确实有道理。在这种情况下,它返回一个布尔值,但通常它返回任何值。所以我必须使用任何?
  • 此回复将受益于解释正确的做事方式,并举例说明。
【解决方案2】:

“无法调用类型缺少调用签名的表达式。”

在您的代码中:

class Post extends Component {
  public toggleBody: string;

  constructor() {
    this.toggleBody = this.setProp('showFullBody');
  }

  public showMore(): boolean {
    return this.toggleBody(true);
  }

  public showLess(): boolean {
    return this.toggleBody(false);
  }
}

你有public toggleBody: string;。您不能将 string 作为函数调用。因此出现错误:this.toggleBody(true);this.toggleBody(false);

【讨论】:

    【解决方案3】:

    让我们分解一下:

    1. 错误提示

      无法调用类型缺少调用签名的表达式。

    2. 代码:

    问题出在这一行public toggleBody: string;&

    这与以下几行有关:

    ...
    return this.toggleBody(true);
    ...
    return this.toggleBody(false);
    
    1. 结果:

    您说toggleBodystring,但是您将其视为具有call signature 的东西(即可以调用的东西的结构:lambdas、proc、函数、方法等。在JS 中只是功能寿。)。您需要将声明更改为public toggleBody: (arg: boolean) =&gt; boolean;

    额外细节:

    “invoke”表示您调用或应用函数。

    Javascript 中的“表达式”基本上是产生值的东西,所以this.toggleBody() 算作表达式。

    “type”在这一行声明public toggleBody: string

    “缺少调用签名”这是因为您试图调用没有签名的 this.toggleBody() 的东西(即可以调用的东西的结构:lambdas、proc、函数、方法等)可以叫做。你说this.toggleBody 就像一个字符串。

    换句话说,错误在说

    无法调用表达式 (this.toggleBody),因为它的类型 (:string) 缺少调用签名(因为它具有字符串签名。)

    【讨论】:

    • 这是有史以来最好的答案之一!我知道所有这些定义,但是当我看到警告信息时,所有这些术语,在一个密集的句子中,对于我混乱的大脑来说太多了。
    【解决方案4】:

    我想你想要的是:

    abstract class Component {
      public deps: any = {};
      public props: any = {};
    
      public makePropSetter<T>(prop: string): (val: T) => T {
        return function(val) {
          this.props[prop] = val
          return val
        }
      }
    }
    
    class Post extends Component {
      public toggleBody: (val: boolean) => boolean;
    
      constructor () {
        super()
        this.toggleBody = this.makePropSetter<boolean>('showFullBody')
      }
    
      showMore (): boolean {
        return this.toggleBody(true)
      }
    
      showLess (): boolean {
        return this.toggleBody(false)
      }
    }
    

    重要的变化在于setProp(即新代码中的makePropSetter)。您真正要做的是说:这是一个函数,它提供了一个属性名称,将返回一个允许您更改该属性的函数。

    makePropSetter 上的 &lt;T&gt; 允许您将该函数锁定为特定类型。子类的构造函数中的&lt;boolean&gt; 实际上是可选的。由于您分配给toggleBody,并且已经完全指定了类型,因此 TS 编译器将能够自行解决。

    然后,在您的子类中,您调用该函数,返回类型现在被正确理解为具有特定签名的函数。当然,您需要让toggleBody 尊重相同的签名。

    【讨论】:

      【解决方案5】:

      这意味着你正在尝试调用不是函数的东西

      const foo = 'string'
      foo() // error
      

      【讨论】:

        【解决方案6】:

        给你的变量添加一个类型然后返回。

        例如:

        const myVariable : string [] = ['hello', 'there'];
        
        const result = myVaraible.map(x=> {
          return
          {
            x.id
          }
        });
        

        => 重要的部分是添加 string[] 类型等:

        【讨论】:

          【解决方案7】:

          我收到了同样的错误信息。就我而言,我无意中将 ES6 export default function myFunc 语法与 const myFunc = require('./myFunc'); 混合在一起。

          改用module.exports = myFunc; 解决了这个问题。

          【讨论】:

            【解决方案8】:

            当您从某事物中请求一个值并将括号放在末尾时,可能会导致此错误,就好像它是一个函数调用一样,但该值在没有结束括号的情况下被正确检索。例如,如果您正在访问的是 Typescript 中的“获取”属性。

            private IMadeAMistakeHere(): void {
                let mynumber = this.SuperCoolNumber();
            }
            
            private IDidItCorrectly(): void {
                let mynumber = this.SuperCoolNumber;
            }
            
            private get SuperCoolNumber(): number {
                let response = 42;
                return response;
            };
            

            【讨论】:

              猜你喜欢
              • 2019-09-10
              • 2019-12-15
              • 2018-12-25
              • 2023-03-20
              • 2019-09-07
              • 1970-01-01
              • 2015-08-26
              • 2017-09-01
              相关资源
              最近更新 更多