The function that it returns has a call signature, but you told Typescript to completely ignore that by adding : any
in its signature.
"Cannot invoke an expression whose type lacks a call signature."
In your code :
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);
}
}
You have public toggleBody: string;
. You cannot call a string
as a function. Hence errors on : this.toggleBody(true);
and this.toggleBody(false);
Let's break this down:
The error says
Cannot invoke an expression whose type lacks a call signature.
The code:
The problem is in this line public toggleBody: string;
&
it's relation to these lines:
...
return this.toggleBody(true);
...
return this.toggleBody(false);
Your saying toggleBody
is a string
but then your treating it like something that has a call signature
(i.e. the structure of something that can be called: lambdas, proc, functions, methods, etc. In JS just function tho.). You need to change the declaration to be public toggleBody: (arg: boolean) => boolean;
.
Extra Details:
"invoke" means your calling or applying a function.
"an expression" in Javascript is basically something that produces a value, so this.toggleBody()
counts as an expression.
"type" is declared on this line public toggleBody: string
"lacks a call signature" this is because your trying to call something this.toggleBody()
that doesn't have signature(i.e. the structure of something that can be called: lambdas, proc, functions, methods, etc.) that can be called. You said this.toggleBody
is something that acts like a string.
In other words the error is saying
Cannot call an expression (this.toggleBody) because it's type (:string) lacks a call signature (bc it has a string signature.)
I think what you want is:
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)
}
}
The important change is in setProp
(i.e., makePropSetter
in the new code). What you're really doing there is to say: this is a function, which provided with a property name, will return a function which allows you to change that property.
The <T>
on makePropSetter
allows you to lock that function in to a specific type. The <boolean>
in the subclass's constructor is actually optional. Since you're assigning to toggleBody
, and that already has the type fully specified, the TS compiler will be able to work it out on its own.
Then, in your subclass, you call that function, and the return type is now properly understood to be a function with a specific signature. Naturally, you'll need to have toggleBody
respect that same signature.
It means you're trying to call something that isn't a function
const foo = 'string'
foo() // error
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With