错误:无法调用类型缺少调用签名的表达式


121

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

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返回的函数确实具有呼叫签名吗?我认为我误解了有关函数类型的一些重要信息,但我不知道它是什么。

谢谢!


1
togglrBody不应该是字符串,因为您希望它是一个函数
eavidan

1
@eavidan是的,它实际上是一个返回布尔值的函数。我本来以为它将返回一个字符串。那我要改成什么呢?
贾斯汀

无论setProp返回什么,似乎<T>(val: T) => T
eavidan

Answers:


76

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

不要那样做


好的进度,谢谢!现在,我收到“错误TS2322:类型'<T>(val:T)=> T'无法分配给类型'布尔'。” 如果我删除:any。我认为这就是为什么我首先添加:any的原因。实际上,我仍然仍然得到原始错误。
贾斯汀

1
如果我这样做并更改public toggleBody: boolean;public toggleBody: any;有效。
贾斯汀

1
@贾斯汀,你为什么还期待其他呢?您声称this.toggleBody应该返回boolean,但这与setProp您为其分配的返回值不一致。您似乎只是随机地输入类型,而没有考虑您实际想要发送和返回的内容。
jonrsharpe

@jonrsharpe好吧,那确实有意义。在这种情况下,它返回一个布尔值,但通常返回任何值。所以我必须使用吗?
贾斯汀

9
举例说明正确的做事方式,将有助于您做出回应。
安德烈·M

38

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

在您的代码中:

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;。您不能将a string作为函数调用。因此,错误:this.toggleBody(true);this.toggleBody(false);


28

让我们分解一下:

  1. 错误说

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

  2. 代码:

问题是,在这条线public toggleBody: string;

与这些行的关系:

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

您的说法toggleBody是“ string但”,然后将其call signature视为具有的事物(即,可以称为的事物的结构:lambda,proc,函数,方法等。在JS中,仅函数tho。)。您需要将声明更改为public toggleBody: (arg: boolean) => boolean;

额外详情:

“调用”是指您调用或应用功能。

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

在此行上声明“类型” public toggleBody: string

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

换句话说,错误是在说

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


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

6

我认为您想要的是:

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在新代码中)。您实际上要说的是:这是一个提供了属性名称的函数,它将返回一个允许您更改该属性的函数。

使用<T>on makePropSetter可以将功能锁定为特定类型。将<boolean>在子类的构造函数实际上是可选的。由于您要分配给toggleBody,并且已经完全指定了类型,因此TS编译器将能够自行进行处理。

然后,在子类中,调用该函数,并且现在可以正确地将返回类型理解为具有特定签名的函数。自然,您需要toggleBody尊重相同的签名。



0

将类型添加到变量中,然后返回。

例如:

const myVariable : string [] = ['hello', 'there'];

const result = myVaraible.map(x=> {
  return
  {
    x.id
  }
});

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


0

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

使用module.exports = myFunc;代替解决了问题。


0

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

private IMadeAMistakeHere(): void {
    let mynumber = this.SuperCoolNumber();
}

private IDidItCorrectly(): void {
    let mynumber = this.SuperCoolNumber;
}

private get SuperCoolNumber(): number {
    let response = 42;
    return response;
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.