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

Jus*_*tin 108 javascript types angularjs typescript

我是打字稿的新手,我有两个班.在父类我有:

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;
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

在孩子班我有:

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

showMore和ShowLess都给出了错误,"无法调用类型缺少调用签名的表达式".

但是,我认为setProp返回DOES的函数有一个调用签名?我想我误解了关于函数类型的重要事情,但我不知道它是什么.

谢谢!

SLa*_*aks 68

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

不要那样做.

  • 举例说明正确的做事方式,将有助于您做出回应。 (5认同)

bas*_*rat 34

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

在你的代码中:

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

你有public toggleBody: string;.你不能称之为string功能.因此错误:this.toggleBody(true);this.toggleBody(false);


Tay*_*sky 25

让我们分解一下:

  1. 错误说

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

  2. 代码:

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

与这些行的关系:

...
return this.toggleBody(true);
...
return this.toggleBody(false);
Run Code Online (Sandbox Code Playgroud)
  1. 结果:

您的说法toggleBody是“ a”,string但随后您将其call signature视为具有“ a ”的事物(即可以称为的结构: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认同)

Gun*_*ner 7

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

const foo = 'string'
foo() // error
Run Code Online (Sandbox Code Playgroud)


And*_*ner 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)
  }
}
Run Code Online (Sandbox Code Playgroud)

重要的变化是setProp(即makePropSetter在新的代码中).你真正在做什么就是说:这是一个提供了属性名称的函数,它将返回一个允许你改变那个属性的函数.

<T>makePropSetter允许您锁定功能的特定类型.将<boolean>在子类的构造函数实际上是可选的.由于您正在分配toggleBody,并且已经完全指定了类型,因此TS编译器将能够自行完成它.

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